diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index cd57ac558c..f137d51c7f 100644 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -290,6 +290,7 @@ if(APPLE) set(SANITIZER_COMMON_SUPPORTED_OS osx) set(BUILTIN_SUPPORTED_OS osx) set(PROFILE_SUPPORTED_OS osx) + set(TSAN_SUPPORTED_OS osx) if(NOT SANITIZER_MIN_OSX_VERSION) string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)" MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}") @@ -547,6 +548,13 @@ else() set(COMPILER_RT_HAS_TSAN FALSE) endif() +if(APPLE) + option(COMPILER_RT_ENABLE_TSAN_OSX "Enable building TSan for OS X - Experimental" Off) + if(COMPILER_RT_ENABLE_TSAN_OSX) + set(COMPILER_RT_HAS_TSAN TRUE) + endif() +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows") set(COMPILER_RT_HAS_UBSAN TRUE) diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h index 4cba61a49f..b736ed9e52 100644 --- a/include/sanitizer/common_interface_defs.h +++ b/include/sanitizer/common_interface_defs.h @@ -105,6 +105,12 @@ extern "C" { int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); + // Similar to __sanitizer_verify_contiguous_container but returns the address + // of the first improperly poisoned byte otherwise. Returns null if the area + // is poisoned properly. + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + // Print the stack trace leading to this call. Useful for debugging user code. void __sanitizer_print_stack_trace(); diff --git a/lib/asan/asan_fake_stack.h b/lib/asan/asan_fake_stack.h index bf1a66cb11..3b1d9eb3b5 100644 --- a/lib/asan/asan_fake_stack.h +++ b/lib/asan/asan_fake_stack.h @@ -155,7 +155,7 @@ class FakeStack { void ForEachFakeFrame(RangeIteratorCallback callback, void *arg); private: - FakeStack() = default; + FakeStack() { } static const uptr kFlagsOffset = 4096; // This is were the flags begin. // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID COMPILER_CHECK(kNumberOfSizeClasses == 11); diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc index 0f0f9bb087..8e23c71be5 100644 --- a/lib/asan/asan_mac.cc +++ b/lib/asan/asan_mac.cc @@ -33,17 +33,17 @@ extern "C" { #endif #include // for dladdr() +#include +#include #include #include +#include +#include // for free() #include #include #include #include -#include -#include -#include // for free() #include -#include namespace __asan { diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc index d7a6307c9b..312c1c34fc 100644 --- a/lib/asan/asan_malloc_mac.cc +++ b/lib/asan/asan_malloc_mac.cc @@ -15,348 +15,51 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC -#include -#include -#include -#include -#include - -#include "asan_allocator.h" #include "asan_interceptors.h" -#include "asan_internal.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" -#include "sanitizer_common/sanitizer_mac.h" - -// Similar code is used in Google Perftools, -// http://code.google.com/p/google-perftools. - -// ---------------------- Replacement functions ---------------- {{{1 -using namespace __asan; // NOLINT - -// TODO(glider): do we need both zones? -static malloc_zone_t *system_malloc_zone = 0; -static malloc_zone_t asan_zone; - -INTERCEPTOR(malloc_zone_t *, malloc_create_zone, - vm_size_t start_size, unsigned zone_flags) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - uptr page_size = GetPageSizeCached(); - uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size); - malloc_zone_t *new_zone = - (malloc_zone_t*)asan_memalign(page_size, allocated_size, - &stack, FROM_MALLOC); - internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone)); - new_zone->zone_name = NULL; // The name will be changed anyway. - if (GetMacosVersion() >= MACOS_VERSION_LION) { - // Prevent the client app from overwriting the zone contents. - // Library functions that need to modify the zone will set PROT_WRITE on it. - // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. - mprotect(new_zone, allocated_size, PROT_READ); - } - return new_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { - // FIXME: ASan should support purgeable allocations. - // https://code.google.com/p/address-sanitizer/issues/detail?id=139 - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); -} - -INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); - // Must return 0 if the contents were not purged since the last call to - // malloc_make_purgeable(). - return 0; -} - -INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { - ENSURE_ASAN_INITED(); - // Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes. - size_t buflen = 6 + (name ? internal_strlen(name) : 0); - InternalScopedString new_name(buflen); - if (name && zone->introspect == asan_zone.introspect) { - new_name.append("asan-%s", name); - name = new_name.data(); - } - - // Call the system malloc's implementation for both external and our zones, - // since that appropriately changes VM region protections on the zone. - REAL(malloc_set_zone_name)(zone, name); -} - -INTERCEPTOR(void *, malloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - void *res = asan_malloc(size, &stack); - return res; -} -INTERCEPTOR(void, free, void *ptr) { - ENSURE_ASAN_INITED(); - if (!ptr) return; - GET_STACK_TRACE_FREE; +using namespace __asan; +#define COMMON_MALLOC_ZONE_NAME "asan" +#define COMMON_MALLOC_ENTER() ENSURE_ASAN_INITED() +#define COMMON_MALLOC_SANITIZER_INITIALIZED asan_inited +#define COMMON_MALLOC_FORCE_LOCK() asan_mz_force_lock() +#define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock() +#define COMMON_MALLOC_MEMALIGN(alignment, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC) +#define COMMON_MALLOC_MALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_malloc(size, &stack) +#define COMMON_MALLOC_REALLOC(ptr, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_realloc(ptr, size, &stack); +#define COMMON_MALLOC_CALLOC(count, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_calloc(count, size, &stack); +#define COMMON_MALLOC_VALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); +#define COMMON_MALLOC_FREE(ptr) \ + GET_STACK_TRACE_FREE; \ asan_free(ptr, &stack, FROM_MALLOC); -} - -INTERCEPTOR(void *, realloc, void *ptr, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); -} - -INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -INTERCEPTOR(void *, valloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -INTERCEPTOR(size_t, malloc_good_size, size_t size) { - ENSURE_ASAN_INITED(); - return asan_zone.introspect->good_size(&asan_zone, size); -} - -INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { - ENSURE_ASAN_INITED(); - CHECK(memptr); - GET_STACK_TRACE_MALLOC; - void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC); - if (result) { - *memptr = result; - return 0; - } - return -1; -} - -namespace { - -// TODO(glider): the __asan_mz_* functions should be united with the Linux -// wrappers, as they are basically copied from there. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -size_t __asan_mz_size(malloc_zone_t* zone, const void* ptr) { - return asan_mz_size(ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_malloc(malloc_zone_t *zone, uptr size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_malloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { - if (UNLIKELY(!asan_inited)) { - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const size_t kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; - static size_t allocated; - size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_valloc(malloc_zone_t *zone, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_valloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -#define GET_ZONE_FOR_PTR(ptr) \ - malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ - const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name - -void ALWAYS_INLINE free_common(void *context, void *ptr) { - if (!ptr) return; - GET_STACK_TRACE_FREE; - // FIXME: need to retire this flag. - if (!flags()->mac_ignore_invalid_free) { - asan_free(ptr, &stack, FROM_MALLOC); - } else { - GET_ZONE_FOR_PTR(ptr); - WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - return; - } -} - -// TODO(glider): the allocation callbacks need to be refactored. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_free(malloc_zone_t *zone, void *ptr) { - free_common(zone, ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { - if (!ptr) { - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); - } else { - if (asan_mz_size(ptr)) { - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); - } else { - // We can't recover from reallocating an unknown address, because - // this would require reading at most |size| bytes from - // potentially unaccessible memory. - GET_STACK_TRACE_FREE; - GET_ZONE_FOR_PTR(ptr); - ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - } - } -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_destroy(malloc_zone_t* zone) { - // A no-op -- we will not be destroyed! - Report("__asan_mz_destroy() called -- ignoring\n"); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_memalign(system_malloc_zone, align, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(align, size, &stack, FROM_MALLOC); -} - -// This function is currently unused, and we build with -Werror. -#if 0 -void __asan_mz_free_definite_size( - malloc_zone_t* zone, void *ptr, size_t size) { - // TODO(glider): check that |size| is valid. - UNIMPLEMENTED(); -} -#endif - -kern_return_t mi_enumerator(task_t task, void *, - unsigned type_mask, vm_address_t zone_address, - memory_reader_t reader, - vm_range_recorder_t recorder) { - // Should enumerate all the pointers we have. Seems like a lot of work. - return KERN_FAILURE; -} - -size_t mi_good_size(malloc_zone_t *zone, size_t size) { - // I think it's always safe to return size, but we maybe could do better. - return size; -} - -boolean_t mi_check(malloc_zone_t *zone) { - UNIMPLEMENTED(); -} - -void mi_print(malloc_zone_t *zone, boolean_t verbose) { - UNIMPLEMENTED(); -} - -void mi_log(malloc_zone_t *zone, void *address) { - // I don't think we support anything like this -} - -void mi_force_lock(malloc_zone_t *zone) { - asan_mz_force_lock(); -} - -void mi_force_unlock(malloc_zone_t *zone) { - asan_mz_force_unlock(); -} - -void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { - AsanMallocStats malloc_stats; - FillMallocStatistics(&malloc_stats); - CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); +#define COMMON_MALLOC_SIZE(ptr) \ + uptr size = asan_mz_size(ptr); +#define COMMON_MALLOC_FILL_STATS(zone, stats) \ + AsanMallocStats malloc_stats; \ + FillMallocStatistics(&malloc_stats); \ + CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); \ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t)); -} - -boolean_t mi_zone_locked(malloc_zone_t *zone) { - // UNIMPLEMENTED(); - return false; -} - -} // unnamed namespace - -namespace __asan { +#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + GET_STACK_TRACE_FREE; \ + ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); +#define COMMON_MALLOC_IGNORE_INVALID_FREE flags()->mac_ignore_invalid_free +#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ + GET_STACK_TRACE_FREE; \ + WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); +#define COMMON_MALLOC_NAMESPACE __asan -void ReplaceSystemMalloc() { - static malloc_introspection_t asan_introspection; - // Ok to use internal_memset, these places are not performance-critical. - internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); +#include "sanitizer_common/sanitizer_malloc_mac.inc" - asan_introspection.enumerator = &mi_enumerator; - asan_introspection.good_size = &mi_good_size; - asan_introspection.check = &mi_check; - asan_introspection.print = &mi_print; - asan_introspection.log = &mi_log; - asan_introspection.force_lock = &mi_force_lock; - asan_introspection.force_unlock = &mi_force_unlock; - asan_introspection.statistics = &mi_statistics; - asan_introspection.zone_locked = &mi_zone_locked; - - internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); - - // Use version 6 for OSX >= 10.6. - asan_zone.version = 6; - asan_zone.zone_name = "asan"; - asan_zone.size = &__asan_mz_size; - asan_zone.malloc = &__asan_mz_malloc; - asan_zone.calloc = &__asan_mz_calloc; - asan_zone.valloc = &__asan_mz_valloc; - asan_zone.free = &__asan_mz_free; - asan_zone.realloc = &__asan_mz_realloc; - asan_zone.destroy = &__asan_mz_destroy; - asan_zone.batch_malloc = 0; - asan_zone.batch_free = 0; - asan_zone.free_definite_size = 0; - asan_zone.memalign = &__asan_mz_memalign; - asan_zone.introspect = &asan_introspection; - - // Register the ASan zone. - malloc_zone_register(&asan_zone); -} -} // namespace __asan - -#endif // SANITIZER_MAC +#endif diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc index 569d359aa4..0082e845fc 100644 --- a/lib/asan/asan_poisoning.cc +++ b/lib/asan/asan_poisoning.cc @@ -375,10 +375,10 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, } } -int __sanitizer_verify_contiguous_container(const void *beg_p, - const void *mid_p, - const void *end_p) { - if (!flags()->detect_container_overflow) return 1; +const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg_p, const void *mid_p, const void *end_p) { + if (!flags()->detect_container_overflow) + return nullptr; uptr beg = reinterpret_cast(beg_p); uptr end = reinterpret_cast(end_p); uptr mid = reinterpret_cast(mid_p); @@ -395,17 +395,24 @@ int __sanitizer_verify_contiguous_container(const void *beg_p, uptr r3_end = end; for (uptr i = r1_beg; i < r1_end; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = r2_beg; i < mid; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = mid; i < r2_end; i++) if (!AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = r3_beg; i < r3_end; i++) if (!AddressIsPoisoned(i)) - return 0; - return 1; + return reinterpret_cast(i); + return nullptr; +} + +int __sanitizer_verify_contiguous_container(const void *beg_p, + const void *mid_p, + const void *end_p) { + return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, + end_p) == nullptr; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index f5a467a29d..28ec076807 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN #include #include diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc index d59f9f5768..d5a14088da 100644 --- a/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -24,6 +24,7 @@ // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DYNAMIC_RUNTIME_THUNK +#define WIN32_LEAN_AND_MEAN #include // First, declare CRT sections we'll be using in this file diff --git a/lib/asan/scripts/asan_device_setup b/lib/asan/scripts/asan_device_setup index 626573c586..338b8d501b 100755 --- a/lib/asan/scripts/asan_device_setup +++ b/lib/asan/scripts/asan_device_setup @@ -276,6 +276,7 @@ if [[ -n "$ASAN_RT64" ]]; then adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true else adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true + adb_pull /system/bin/app_process32 "$TMPDIROLD" || true adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true fi @@ -401,6 +402,7 @@ if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then install "$TMPDIR/asanwrapper64" /system/bin 755 else install "$TMPDIR/$ASAN_RT" /system/lib 644 + install "$TMPDIR/app_process32" /system/bin 755 $CTX install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX install "$TMPDIR/asanwrapper" /system/bin 755 $CTX diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py index 5b519e3acd..e6d43cd3f4 100755 --- a/lib/asan/scripts/asan_symbolize.py +++ b/lib/asan/scripts/asan_symbolize.py @@ -77,7 +77,7 @@ def open_llvm_symbolizer(self): cmd = [self.symbolizer_path, '--use-symbol-table=true', '--demangle=%s' % demangle, - '--functions=short', + '--functions=linkage', '--inlining=true', '--default-arch=%s' % self.default_arch] if self.system == 'Darwin': diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index d6a972e5a5..97249ea730 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -176,7 +176,8 @@ if (NOT MSVC) if (WIN32) set(x86_64_SOURCES ${x86_64_SOURCES} - x86_64/chkstk.S) + x86_64/chkstk.S + x86_64/chkstk2.S) endif() set(i386_SOURCES @@ -199,7 +200,8 @@ if (NOT MSVC) if (WIN32) set(i386_SOURCES ${i386_SOURCES} - i386/chkstk.S) + i386/chkstk.S + i386/chkstk2.S) endif() set(i686_SOURCES @@ -347,7 +349,7 @@ if (APPLE) add_subdirectory(Darwin-excludes) add_subdirectory(macho_embedded) darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) -elseif (NOT WIN32 OR MINGW) +else () foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) # Filter out generic versions of routines that are re-implemented in @@ -361,11 +363,18 @@ elseif (NOT WIN32 OR MINGW) endif () endforeach () + # Rust: don't insert a reference to MSVCRT.lib/etc + if (MSVC) + set(_cflags -Zl) + else () + set(_cflags -std=c99) + endif () + add_compiler_rt_runtime(clang_rt.builtins STATIC ARCHS ${arch} SOURCES ${${arch}_SOURCES} - CFLAGS "-std=c99" + CFLAGS ${_cflags} PARENT_TARGET builtins) endif () endforeach () diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c index ede7659a05..5e3fcccd23 100644 --- a/lib/builtins/clear_cache.c +++ b/lib/builtins/clear_cache.c @@ -24,9 +24,13 @@ #endif #if defined(__mips__) + #include + // Rust: For some strange reason __USE_MISC isn't being defined so + // we don't get the definition of syscall. Force it to be defined. + #define __USE_MISC + #include #include #include - #include #if defined(__ANDROID__) && defined(__LP64__) /* * clear_mips_cache - Invalidates instruction cache for Mips. @@ -104,7 +108,7 @@ void __clear_cache(void *start, void *end) { const register int flags __asm("r2") = 0; const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush; __asm __volatile("svc 0x0" : "=r"(start_reg) - : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0"); + : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags)); if (start_reg != 0) { compilerrt_abort(); } diff --git a/lib/builtins/emutls.c b/lib/builtins/emutls.c index 09e79568bd..d4678e9ebc 100644 --- a/lib/builtins/emutls.c +++ b/lib/builtins/emutls.c @@ -8,6 +8,15 @@ * ===----------------------------------------------------------------------=== */ #include + +// Rust-specific change +// One of the headers included by pthread.h in Android #defines si_int to +// something else. Remove this definition, as we use si_int internally to +// mean int. +#ifdef si_int +#undef si_int +#endif + #include #include #include diff --git a/lib/builtins/fp_fixuint_impl.inc b/lib/builtins/fp_fixuint_impl.inc index b223c63840..d68ccf27a7 100644 --- a/lib/builtins/fp_fixuint_impl.inc +++ b/lib/builtins/fp_fixuint_impl.inc @@ -27,7 +27,7 @@ static __inline fixuint_t __fixuint(fp_t a) { return 0; // If the value is too large for the integer type, saturate. - if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT) + if ((unsigned)exponent >= sizeof(fixuint_t) * CHAR_BIT) return ~(fixuint_t)0; // If 0 <= exponent < significandBits, right shift to get the result. diff --git a/lib/builtins/gcc_personality_v0.c b/lib/builtins/gcc_personality_v0.c index 331dc2bea2..afe643c4bd 100644 --- a/lib/builtins/gcc_personality_v0.c +++ b/lib/builtins/gcc_personality_v0.c @@ -164,8 +164,6 @@ __gcc_personality_v0(int version, _Unwind_Action actions, return _URC_CONTINUE_UNWIND; uintptr_t pc = _Unwind_GetIP(context)-1; - uintptr_t funcStart = _Unwind_GetRegionStart(context); - uintptr_t pcOffset = pc - funcStart; /* Parse LSDA header. */ uint8_t lpStartEncoding = *lsda++; @@ -176,17 +174,43 @@ __gcc_personality_v0(int version, _Unwind_Action actions, if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } - /* Walk call-site table looking for range that includes current PC. */ + + uintptr_t resumeIp = 0; uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); - const uint8_t* callSiteTableStart = lsda; - const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; - const uint8_t* p=callSiteTableStart; - while (p < callSiteTableEnd) { - uintptr_t start = readEncodedPointer(&p, callSiteEncoding); - uintptr_t length = readEncodedPointer(&p, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); - readULEB128(&p); /* action value not used for C code */ + const uint8_t* callSite = lsda; + +#if defined(__USING_SJLJ_EXCEPTIONS__) + (void)callSiteEncoding; + (void)callSiteTableLength; + /* The given "IP" is an index into the call-site table, with two + exceptions -- -1 means no-action, and 0 means terminate. But + since we're using uleb128 values, we've not got random access + to the array. */ + if ((int) pc <= 0) { + return _URC_CONTINUE_UNWIND; + } else { + uintptr_t csLp; + do { + csLp = readULEB128(&callSite); + readULEB128(&callSite); // skip cs action + } while (--pc); + + /* Can never have null landing pad for sjlj -- that would have + been indicated by a -1 call site index. */ + resumeIp = csLp + 1; + } +#else + /* Walk call-site table looking for range that includes current PC. */ + uintptr_t funcStart = _Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + const uint8_t* callSiteTableEnd = callSite + callSiteTableLength; + + while (callSite < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t length = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t landingPad = readEncodedPointer(&callSite, callSiteEncoding); + readULEB128(&callSite); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { @@ -195,15 +219,20 @@ __gcc_personality_v0(int version, _Unwind_Action actions, * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. */ - _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), - (uintptr_t)exceptionObject); - _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); - _Unwind_SetIP(context, (funcStart + landingPad)); - return _URC_INSTALL_CONTEXT; + resumeIp = funcStart + landingPad; + break; } } +#endif // SJ/LJ - /* No landing pad found, continue unwinding. */ - return _URC_CONTINUE_UNWIND; + if (resumeIp == 0) { + return _URC_CONTINUE_UNWIND; + } else { + _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), + (uintptr_t)exceptionObject); + _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); + _Unwind_SetIP(context, resumeIp); + return _URC_INSTALL_CONTEXT; + } } diff --git a/lib/builtins/i386/chkstk.S b/lib/builtins/i386/chkstk.S index 3733d722ef..b59974868f 100644 --- a/lib/builtins/i386/chkstk.S +++ b/lib/builtins/i386/chkstk.S @@ -19,13 +19,13 @@ DEFINE_COMPILERRT_FUNCTION(__chkstk_ms) jb 1f 2: sub $0x1000,%ecx - orl $0,(%ecx) + test %ecx,(%ecx) sub $0x1000,%eax cmp $0x1000,%eax ja 2b 1: sub %eax,%ecx - orl $0,(%ecx) + test %ecx,(%ecx) pop %eax pop %ecx ret diff --git a/lib/builtins/i386/chkstk2.S b/lib/builtins/i386/chkstk2.S new file mode 100644 index 0000000000..7d65bb0889 --- /dev/null +++ b/lib/builtins/i386/chkstk2.S @@ -0,0 +1,40 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +#ifdef __i386__ + +// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments, +// then decrement %esp by %eax. Preserves all registers except %esp and flags. +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(_alloca) // _chkstk and _alloca are the same function +DEFINE_COMPILERRT_FUNCTION(__chkstk) + push %ecx + cmp $0x1000,%eax + lea 8(%esp),%ecx // esp before calling this routine -> ecx + jb 1f +2: + sub $0x1000,%ecx + test %ecx,(%ecx) + sub $0x1000,%eax + cmp $0x1000,%eax + ja 2b +1: + sub %eax,%ecx + test %ecx,(%ecx) + + lea 4(%esp),%eax // load pointer to the return address into eax + mov %ecx,%esp // install the new top of stack pointer into esp + mov -4(%eax),%ecx // restore ecx + push (%eax) // push return address onto the stack + sub %esp,%eax // restore the original value in eax + ret +END_COMPILERRT_FUNCTION(__chkstk) +END_COMPILERRT_FUNCTION(_alloca) + +#endif // __i386__ diff --git a/lib/builtins/int_endianness.h b/lib/builtins/int_endianness.h index 7995ddbb95..92511e6a15 100644 --- a/lib/builtins/int_endianness.h +++ b/lib/builtins/int_endianness.h @@ -105,6 +105,19 @@ #endif /* Windows */ +#if defined(__linux__) +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* __BYTE_ORDER */ + +#endif /* GNU/Linux */ + #endif /* Clang or GCC. */ /* . */ diff --git a/lib/builtins/int_math.h b/lib/builtins/int_math.h index fc81fb7f02..9a8b751e44 100644 --- a/lib/builtins/int_math.h +++ b/lib/builtins/int_math.h @@ -28,7 +28,9 @@ #if defined(_MSC_VER) && !defined(__clang__) #include #include -#include +// Rust: need to upstream this +// don't include ymath.h, it's not needed + pulls in the C++ stdlib for some reason +// #include #endif #if defined(_MSC_VER) && !defined(__clang__) diff --git a/lib/builtins/x86_64/chkstk.S b/lib/builtins/x86_64/chkstk.S index 5759e84498..4149ac63d9 100644 --- a/lib/builtins/x86_64/chkstk.S +++ b/lib/builtins/x86_64/chkstk.S @@ -24,13 +24,13 @@ DEFINE_COMPILERRT_FUNCTION(___chkstk_ms) jb 1f 2: sub $0x1000,%rcx - orl $0,(%rcx) + test %rcx,(%rcx) sub $0x1000,%rax cmp $0x1000,%rax ja 2b 1: sub %rax,%rcx - orl $0,(%rcx) + test %rcx,(%rcx) pop %rax pop %rcx ret diff --git a/lib/builtins/x86_64/chkstk2.S b/lib/builtins/x86_64/chkstk2.S new file mode 100644 index 0000000000..ac1eb920e0 --- /dev/null +++ b/lib/builtins/x86_64/chkstk2.S @@ -0,0 +1,42 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +#ifdef __x86_64__ + +// _chkstk (_alloca) routine - probe stack between %rsp and (%rsp-%rax) in 4k increments, +// then decrement %rsp by %rax. Preserves all registers except %rsp and flags. +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(__alloca) + mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx + // fallthrough +DEFINE_COMPILERRT_FUNCTION(___chkstk) + push %rcx + cmp $0x1000,%rax + lea 16(%rsp),%rcx // rsp before calling this routine -> rcx + jb 1f +2: + sub $0x1000,%rcx + test %rcx,(%rcx) + sub $0x1000,%rax + cmp $0x1000,%rax + ja 2b +1: + sub %rax,%rcx + test %rcx,(%rcx) + + lea 8(%rsp),%rax // load pointer to the return address into rax + mov %rcx,%rsp // install the new top of stack pointer into rsp + mov -8(%rax),%rcx // restore rcx + push (%rax) // push return address onto the stack + sub %rsp,%rax // restore the original value in rax + ret +END_COMPILERRT_FUNCTION(___chkstk) +END_COMPILERRT_FUNCTION(__alloca) + +#endif // __x86_64__ diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc index e3197ddc1a..4c04c83b98 100644 --- a/lib/interception/interception_win.cc +++ b/lib/interception/interception_win.cc @@ -15,6 +15,7 @@ #ifdef _WIN32 #include "interception.h" +#define WIN32_LEAN_AND_MEAN #include namespace __interception { diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc index 87f2cdf2e9..b64dcb6ffe 100644 --- a/lib/msan/msan.cc +++ b/lib/msan/msan.cc @@ -380,8 +380,6 @@ void __msan_init() { CacheBinaryName(); InitializeFlags(); - CheckVMASize(); - __sanitizer_set_report_path(common_flags()->log_path); InitializeInterceptors(); diff --git a/lib/msan/msan.h b/lib/msan/msan.h index 2d779834a1..2079a592b7 100644 --- a/lib/msan/msan.h +++ b/lib/msan/msan.h @@ -54,44 +54,58 @@ const MappingDesc kMemoryLayout[] = { #elif SANITIZER_LINUX && defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 +// The mapping describes both 39-bits and 42-bits. AArch64 maps: +// - 0x00000000000-0x00010000000: 39/42-bits program own segments +// - 0x05500000000-0x05600000000: 39-bits PIE program segments +// - 0x07f80000000-0x07fffffffff: 39-bits libraries segments +// - 0x2aa00000000-0x2ab00000000: 42-bits PIE program segments +// - 0x3ff00000000-0x3ffffffffff: 42-bits libraries segments +// It is fragmented in multiples segments to increase the memory available +// on 42-bits (12.21% of total VMA available for 42-bits and 13.28 for +// 39 bits). const MappingDesc kMemoryLayout[] = { - {0x0000000000ULL, 0x4000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x4000000000ULL, 0x4300000000ULL, MappingDesc::SHADOW, "shadow"}, - {0x4300000000ULL, 0x4600000000ULL, MappingDesc::ORIGIN, "origin"}, - {0x4600000000ULL, 0x5500000000ULL, MappingDesc::INVALID, "invalid"}, - {0x5500000000ULL, 0x5600000000ULL, MappingDesc::APP, "app"}, - {0x5600000000ULL, 0x7000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x7000000000ULL, 0x8000000000ULL, MappingDesc::APP, "app"} + {0x00000000000ULL, 0x01000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x01000000000ULL, 0x02000000000ULL, MappingDesc::SHADOW, "shadow-2"}, + {0x02000000000ULL, 0x03000000000ULL, MappingDesc::ORIGIN, "origin-2"}, + {0x03000000000ULL, 0x04000000000ULL, MappingDesc::SHADOW, "shadow-1"}, + {0x04000000000ULL, 0x05000000000ULL, MappingDesc::ORIGIN, "origin-1"}, + {0x05000000000ULL, 0x06000000000ULL, MappingDesc::APP, "app-1"}, + {0x06000000000ULL, 0x07000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x07000000000ULL, 0x08000000000ULL, MappingDesc::APP, "app-2"}, + {0x08000000000ULL, 0x09000000000ULL, MappingDesc::INVALID, "invalid"}, + // The mappings below are used only for 42-bits VMA. + {0x09000000000ULL, 0x0A000000000ULL, MappingDesc::SHADOW, "shadow-3"}, + {0x0A000000000ULL, 0x0B000000000ULL, MappingDesc::ORIGIN, "origin-3"}, + {0x0B000000000ULL, 0x0F000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x0F000000000ULL, 0x10000000000ULL, MappingDesc::APP, "app-3"}, + {0x10000000000ULL, 0x11000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x11000000000ULL, 0x12000000000ULL, MappingDesc::APP, "app-4"}, + {0x12000000000ULL, 0x17000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x17000000000ULL, 0x18000000000ULL, MappingDesc::SHADOW, "shadow-4"}, + {0x18000000000ULL, 0x19000000000ULL, MappingDesc::ORIGIN, "origin-4"}, + {0x19000000000ULL, 0x20000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x20000000000ULL, 0x21000000000ULL, MappingDesc::APP, "app-5"}, + {0x21000000000ULL, 0x26000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x26000000000ULL, 0x27000000000ULL, MappingDesc::SHADOW, "shadow-5"}, + {0x27000000000ULL, 0x28000000000ULL, MappingDesc::ORIGIN, "origin-5"}, + {0x28000000000ULL, 0x29000000000ULL, MappingDesc::SHADOW, "shadow-7"}, + {0x29000000000ULL, 0x2A000000000ULL, MappingDesc::ORIGIN, "origin-7"}, + {0x2A000000000ULL, 0x2B000000000ULL, MappingDesc::APP, "app-6"}, + {0x2B000000000ULL, 0x2C000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x2C000000000ULL, 0x2D000000000ULL, MappingDesc::SHADOW, "shadow-6"}, + {0x2D000000000ULL, 0x2E000000000ULL, MappingDesc::ORIGIN, "origin-6"}, + {0x2E000000000ULL, 0x2F000000000ULL, MappingDesc::APP, "app-7"}, + {0x2F000000000ULL, 0x39000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x39000000000ULL, 0x3A000000000ULL, MappingDesc::SHADOW, "shadow-9"}, + {0x3A000000000ULL, 0x3B000000000ULL, MappingDesc::ORIGIN, "origin-9"}, + {0x3B000000000ULL, 0x3C000000000ULL, MappingDesc::APP, "app-8"}, + {0x3C000000000ULL, 0x3D000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x3D000000000ULL, 0x3E000000000ULL, MappingDesc::SHADOW, "shadow-8"}, + {0x3E000000000ULL, 0x3F000000000ULL, MappingDesc::ORIGIN, "origin-8"}, + {0x3F000000000ULL, 0x40000000000ULL, MappingDesc::APP, "app-9"}, }; -// Maps low and high app ranges to contiguous space with zero base: -// Low: 55 0000 0000 - 55 ffff ffff -> 1 0000 0000 - 1 ffff ffff -// High: 70 0000 0000 - 7f ffff ffff -> 0 0000 0000 - f ffff ffff -# define LINEARIZE_MEM(mem) \ - (((uptr)(mem) & ~0x7C00000000ULL) ^ 0x100000000ULL) -# define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x4000000000ULL) -# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x300000000ULL) - -# elif SANITIZER_AARCH64_VMA == 42 -const MappingDesc kMemoryLayout[] = { - {0x00000000000ULL, 0x10000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x10000000000ULL, 0x11b00000000ULL, MappingDesc::SHADOW, "shadow"}, - {0x11b00000000ULL, 0x12000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x12000000000ULL, 0x13b00000000ULL, MappingDesc::ORIGIN, "origin"}, - {0x13b00000000ULL, 0x2aa00000000ULL, MappingDesc::INVALID, "invalid"}, - {0x2aa00000000ULL, 0x2ab00000000ULL, MappingDesc::APP, "app"}, - {0x2ab00000000ULL, 0x3f000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x3f000000000ULL, 0x40000000000ULL, MappingDesc::APP, "app"}, -}; -// Maps low and high app ranges to contigous space with zero base: -// 2 aa00 0000 00 - 2 ab00 0000 00: -> 1a00 0000 00 - 1aff ffff ff -// 3 f000 0000 00 - 4 0000 0000 00: -> 0000 0000 00 - 0fff ffff ff -# define LINEARIZE_MEM(mem) \ - (((uptr)(mem) & ~0x3E000000000ULL) ^ 0x1000000000ULL) -# define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x10000000000ULL) -# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL) - -# endif // SANITIZER_AARCH64_VMA +# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0x6000000000ULL) +# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x1000000000ULL) #elif SANITIZER_LINUX && defined(__powerpc64__) diff --git a/lib/msan/msan_allocator.h b/lib/msan/msan_allocator.h index a9a27e1057..407942e54c 100644 --- a/lib/msan/msan_allocator.h +++ b/lib/msan/msan_allocator.h @@ -26,7 +26,7 @@ struct MsanThreadLocalMallocStorage { private: // These objects are allocated via mmap() and are zero-initialized. - MsanThreadLocalMallocStorage() = default; + MsanThreadLocalMallocStorage() {} }; } // namespace __msan diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc index 2888eb528d..ab3be91fcf 100644 --- a/lib/msan/msan_linux.cc +++ b/lib/msan/msan_linux.cc @@ -119,12 +119,18 @@ bool InitShadow(bool init_origins) { return false; } + const uptr maxVirtualAddress = GetMaxVirtualAddress(); + for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { uptr start = kMemoryLayout[i].start; uptr end = kMemoryLayout[i].end; uptr size= end - start; MappingDesc::Type type = kMemoryLayout[i].type; + // Check if the segment should be mapped based on platform constraints. + if (start >= maxVirtualAddress) + continue; + bool map = type == MappingDesc::SHADOW || (init_origins && type == MappingDesc::ORIGIN); bool protect = type == MappingDesc::INVALID || diff --git a/lib/sanitizer_common/sanitizer_bitvector.h b/lib/sanitizer_common/sanitizer_bitvector.h index ef61486bff..d8472732ff 100644 --- a/lib/sanitizer_common/sanitizer_bitvector.h +++ b/lib/sanitizer_common/sanitizer_bitvector.h @@ -87,7 +87,7 @@ class BasicBitVector { // } class Iterator { public: - Iterator() = default; + Iterator() { } explicit Iterator(const BasicBitVector &bv) : bv_(bv) {} bool hasNext() const { return !bv_.empty(); } uptr next() { return bv_.getAndClearFirstOne(); } @@ -273,7 +273,7 @@ class TwoLevelBitVector { // } class Iterator { public: - Iterator() = default; + Iterator() { } explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) { it1_.clear(); it2_.clear(); diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 2fb88688d1..b40a457c0b 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -164,7 +164,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, } void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - error_t err) { + const char *mmap_type, error_t err) { static int recursion_count; if (recursion_count) { // The Report() and CHECK calls below may call mmap recursively and fail. @@ -174,8 +174,8 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, } recursion_count++; Report("ERROR: %s failed to " - "allocate 0x%zx (%zd) bytes of %s (error code: %d)\n", - SanitizerToolName, size, size, mem_type, err); + "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", + SanitizerToolName, mmap_type, size, size, mem_type, err); DumpProcessMap(); UNREACHABLE("unable to mmap"); } diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index bfd0d6e12a..43cd2d0e8c 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -309,7 +309,7 @@ void NORETURN Die(); void NORETURN CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - error_t err); + const char *mmap_type, error_t err); // Set the name of the current thread to 'name', return true on succees. // The name may be truncated to a system-dependent limit. diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 26fb916e68..62902a306c 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -441,6 +441,8 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { #if SANITIZER_INTERCEPT_MEMCHR INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) { + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) + return internal_memchr(s, c, n); void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n); void *res = REAL(memchr)(s, c, n); @@ -2446,6 +2448,7 @@ INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry, INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data); + __sanitizer_iovec local_iovec; if (data) { if (request == ptrace_setregs) @@ -2454,11 +2457,19 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz); else if (request == ptrace_setfpxregs) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz); + else if (request == ptrace_setvfpregs) + COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_setsiginfo) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz); - else if (request == ptrace_setregset) { - __sanitizer_iovec *iov = (__sanitizer_iovec *)data; - COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len); + // Some kernel might zero the iovec::iov_base in case of invalid + // write access. In this case copy the invalid address for further + // inspection. + else if (request == ptrace_setregset || request == ptrace_getregset) { + __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; + COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec)); + local_iovec = *iovec; + if (request == ptrace_setregset) + COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len); } } @@ -2476,13 +2487,17 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz); else if (request == ptrace_getfpxregs) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz); + else if (request == ptrace_getvfpregs) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_getsiginfo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz); else if (request == ptrace_geteventmsg) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long)); else if (request == ptrace_getregset) { - __sanitizer_iovec *iov = (__sanitizer_iovec *)data; - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len); + __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base, + local_iovec.iov_len); } } return res; diff --git a/lib/sanitizer_common/sanitizer_interface_internal.h b/lib/sanitizer_common/sanitizer_interface_internal.h index 94d9f4e952..b11ae30106 100644 --- a/lib/sanitizer_common/sanitizer_interface_internal.h +++ b/lib/sanitizer_common/sanitizer_interface_internal.h @@ -53,6 +53,9 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); -} // extern "C" + SANITIZER_INTERFACE_ATTRIBUTE + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + } // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H diff --git a/lib/sanitizer_common/sanitizer_libignore.cc b/lib/sanitizer_common/sanitizer_libignore.cc index fabd335856..545393966b 100644 --- a/lib/sanitizer_common/sanitizer_libignore.cc +++ b/lib/sanitizer_common/sanitizer_libignore.cc @@ -9,7 +9,7 @@ #include "sanitizer_platform.h" -#if SANITIZER_FREEBSD || SANITIZER_LINUX +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC #include "sanitizer_libignore.h" #include "sanitizer_flags.h" diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 97c65676bf..4b583bfa41 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -62,20 +62,6 @@ namespace __sanitizer { -// This function is defined elsewhere if we intercepted pthread_attr_getstack. -extern "C" { -SANITIZER_WEAK_ATTRIBUTE int -real_pthread_attr_getstack(void *attr, void **addr, size_t *size); -} // extern "C" - -static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { -#if !SANITIZER_GO - if (&real_pthread_attr_getstack) - return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -#endif - return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -} - SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act, void *oldact); @@ -128,7 +114,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); uptr stacksize = 0; void *stackaddr = nullptr; - my_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); + my_pthread_attr_getstack(&attr, &stackaddr, &stacksize); pthread_attr_destroy(&attr); CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check. @@ -400,33 +386,6 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, #endif } -#if !SANITIZER_GO -void AdjustStackSize(void *attr_) { - pthread_attr_t *attr = (pthread_attr_t *)attr_; - uptr stackaddr = 0; - size_t stacksize = 0; - my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); - // GLibC will return (0 - stacksize) as the stack address in the case when - // stacksize is set, but stackaddr is not. - bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); - // We place a lot of tool data into TLS, account for that. - const uptr minstacksize = GetTlsSize() + 128*1024; - if (stacksize < minstacksize) { - if (!stack_set) { - if (stacksize != 0) { - VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, - minstacksize); - pthread_attr_setstacksize(attr, minstacksize); - } - } else { - Printf("Sanitizer: pre-allocated stack size is insufficient: " - "%zu < %zu\n", stacksize, minstacksize); - Printf("Sanitizer: pthread_create is likely to fail.\n"); - } - } -} -#endif // !SANITIZER_GO - # if !SANITIZER_FREEBSD typedef ElfW(Phdr) Elf_Phdr; # elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index d448ddaba6..3151cf8b91 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -41,6 +41,7 @@ extern char **environ; #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ namespace __sanitizer { // ---------------------- sanitizer_libc.h uptr internal_mmap(void *addr, size_t length, int prot, int flags, int fd, u64 offset) { + if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL); return (uptr)mmap(addr, length, prot, flags, fd, offset); } diff --git a/lib/sanitizer_common/sanitizer_malloc_mac.inc b/lib/sanitizer_common/sanitizer_malloc_mac.inc new file mode 100644 index 0000000000..33e9d96b8c --- /dev/null +++ b/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -0,0 +1,350 @@ +//===-- sanitizer_malloc_mac.inc --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains Mac-specific malloc interceptors and a custom zone +// implementation, which together replace the system allocator. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if !SANITIZER_MAC +#error "This file should only be compiled on Darwin." +#endif + +#include +#include +#include +#include +#include + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_mac.h" + +// Similar code is used in Google Perftools, +// http://code.google.com/p/google-perftools. + +// TODO(glider): do we need both zones? +static malloc_zone_t *system_malloc_zone = 0; +static malloc_zone_t sanitizer_zone; + +INTERCEPTOR(malloc_zone_t *, malloc_create_zone, + vm_size_t start_size, unsigned zone_flags) { + COMMON_MALLOC_ENTER(); + uptr page_size = GetPageSizeCached(); + uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size); + COMMON_MALLOC_MEMALIGN(page_size, allocated_size); + malloc_zone_t *new_zone = (malloc_zone_t *)p; + internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone)); + new_zone->zone_name = NULL; // The name will be changed anyway. + if (GetMacosVersion() >= MACOS_VERSION_LION) { + // Prevent the client app from overwriting the zone contents. + // Library functions that need to modify the zone will set PROT_WRITE on it. + // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. + mprotect(new_zone, allocated_size, PROT_READ); + } + return new_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { + COMMON_MALLOC_ENTER(); + return &sanitizer_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { + // FIXME: ASan should support purgeable allocations. + // https://code.google.com/p/address-sanitizer/issues/detail?id=139 + COMMON_MALLOC_ENTER(); + return &sanitizer_zone; +} + +INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + COMMON_MALLOC_ENTER(); +} + +INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + COMMON_MALLOC_ENTER(); + // Must return 0 if the contents were not purged since the last call to + // malloc_make_purgeable(). + return 0; +} + +INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { + COMMON_MALLOC_ENTER(); + // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)| + // bytes. + size_t buflen = + sizeof(COMMON_MALLOC_ZONE_NAME "-") + (name ? internal_strlen(name) : 0); + InternalScopedString new_name(buflen); + if (name && zone->introspect == sanitizer_zone.introspect) { + new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name); + name = new_name.data(); + } + + // Call the system malloc's implementation for both external and our zones, + // since that appropriately changes VM region protections on the zone. + REAL(malloc_set_zone_name)(zone, name); +} + +INTERCEPTOR(void *, malloc, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_MALLOC(size); + return p; +} + +INTERCEPTOR(void, free, void *ptr) { + COMMON_MALLOC_ENTER(); + if (!ptr) return; + COMMON_MALLOC_FREE(ptr); +} + +INTERCEPTOR(void *, realloc, void *ptr, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_REALLOC(ptr, size); + return p; +} + +INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_CALLOC(nmemb, size); + return p; +} + +INTERCEPTOR(void *, valloc, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_VALLOC(size); + return p; +} + +INTERCEPTOR(size_t, malloc_good_size, size_t size) { + COMMON_MALLOC_ENTER(); + return sanitizer_zone.introspect->good_size(&sanitizer_zone, size); +} + +INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { + COMMON_MALLOC_ENTER(); + CHECK(memptr); + COMMON_MALLOC_MEMALIGN(alignment, size); + if (p) { + *memptr = p; + return 0; + } + return -1; +} + +namespace { + +// TODO(glider): the __sanitizer_mz_* functions should be united with the Linux +// wrappers, as they are basically copied from there. +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +size_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) { + COMMON_MALLOC_SIZE(ptr); + return size; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_malloc(system_malloc_zone, size); + } + COMMON_MALLOC_MALLOC(size); + return p; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. + const size_t kCallocPoolSize = 1024; + static uptr calloc_memory_for_dlsym[kCallocPoolSize]; + static size_t allocated; + size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; + void *mem = (void*)&calloc_memory_for_dlsym[allocated]; + allocated += size_in_words; + CHECK(allocated < kCallocPoolSize); + return mem; + } + COMMON_MALLOC_CALLOC(nmemb, size); + return p; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_valloc(system_malloc_zone, size); + } + COMMON_MALLOC_VALLOC(size); + return p; +} + +#define GET_ZONE_FOR_PTR(ptr) \ + malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ + const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name + +void ALWAYS_INLINE free_common(void *context, void *ptr) { + if (!ptr) return; + // FIXME: need to retire this flag. + if (!COMMON_MALLOC_IGNORE_INVALID_FREE) { + COMMON_MALLOC_FREE(ptr); + } else { + GET_ZONE_FOR_PTR(ptr); + COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name); + } +} + +// TODO(glider): the allocation callbacks need to be refactored. +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) { + free_common(zone, ptr); +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) { + if (!ptr) { + COMMON_MALLOC_MALLOC(new_size); + return p; + } else { + COMMON_MALLOC_SIZE(ptr); + if (size) { + COMMON_MALLOC_REALLOC(ptr, new_size); + return p; + } else { + // We can't recover from reallocating an unknown address, because + // this would require reading at most |new_size| bytes from + // potentially unaccessible memory. + GET_ZONE_FOR_PTR(ptr); + COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name); + return nullptr; + } + } +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_mz_destroy(malloc_zone_t* zone) { + // A no-op -- we will not be destroyed! + Report("__sanitizer_mz_destroy() called -- ignoring\n"); +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_memalign(system_malloc_zone, align, size); + } + COMMON_MALLOC_MEMALIGN(align, size); + return p; +} + +// This function is currently unused, and we build with -Werror. +#if 0 +void __sanitizer_mz_free_definite_size( + malloc_zone_t* zone, void *ptr, size_t size) { + // TODO(glider): check that |size| is valid. + UNIMPLEMENTED(); +} +#endif + +kern_return_t mi_enumerator(task_t task, void *, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) { + // Should enumerate all the pointers we have. Seems like a lot of work. + return KERN_FAILURE; +} + +size_t mi_good_size(malloc_zone_t *zone, size_t size) { + // I think it's always safe to return size, but we maybe could do better. + return size; +} + +boolean_t mi_check(malloc_zone_t *zone) { + UNIMPLEMENTED(); +} + +void mi_print(malloc_zone_t *zone, boolean_t verbose) { + UNIMPLEMENTED(); +} + +void mi_log(malloc_zone_t *zone, void *address) { + // I don't think we support anything like this +} + +void mi_force_lock(malloc_zone_t *zone) { + COMMON_MALLOC_FORCE_LOCK(); +} + +void mi_force_unlock(malloc_zone_t *zone) { + COMMON_MALLOC_FORCE_UNLOCK(); +} + +void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + COMMON_MALLOC_FILL_STATS(zone, stats); +} + +boolean_t mi_zone_locked(malloc_zone_t *zone) { + // UNIMPLEMENTED(); + return false; +} + +} // unnamed namespace + +namespace COMMON_MALLOC_NAMESPACE { + +void ReplaceSystemMalloc() { + static malloc_introspection_t sanitizer_zone_introspection; + // Ok to use internal_memset, these places are not performance-critical. + internal_memset(&sanitizer_zone_introspection, 0, + sizeof(sanitizer_zone_introspection)); + + sanitizer_zone_introspection.enumerator = &mi_enumerator; + sanitizer_zone_introspection.good_size = &mi_good_size; + sanitizer_zone_introspection.check = &mi_check; + sanitizer_zone_introspection.print = &mi_print; + sanitizer_zone_introspection.log = &mi_log; + sanitizer_zone_introspection.force_lock = &mi_force_lock; + sanitizer_zone_introspection.force_unlock = &mi_force_unlock; + sanitizer_zone_introspection.statistics = &mi_statistics; + sanitizer_zone_introspection.zone_locked = &mi_zone_locked; + + internal_memset(&sanitizer_zone, 0, sizeof(malloc_zone_t)); + + // Use version 6 for OSX >= 10.6. + sanitizer_zone.version = 6; + sanitizer_zone.zone_name = COMMON_MALLOC_ZONE_NAME; + sanitizer_zone.size = &__sanitizer_mz_size; + sanitizer_zone.malloc = &__sanitizer_mz_malloc; + sanitizer_zone.calloc = &__sanitizer_mz_calloc; + sanitizer_zone.valloc = &__sanitizer_mz_valloc; + sanitizer_zone.free = &__sanitizer_mz_free; + sanitizer_zone.realloc = &__sanitizer_mz_realloc; + sanitizer_zone.destroy = &__sanitizer_mz_destroy; + sanitizer_zone.batch_malloc = 0; + sanitizer_zone.batch_free = 0; + sanitizer_zone.free_definite_size = 0; + sanitizer_zone.memalign = &__sanitizer_mz_memalign; + sanitizer_zone.introspect = &sanitizer_zone_introspection; + + // Register the zone. + malloc_zone_register(&sanitizer_zone); +} + +} // namespace COMMON_MALLOC_NAMESPACE diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index 03dba853b1..89bfe98897 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -133,7 +133,7 @@ #define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_PTRACE SI_LINUX_NOT_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) #define SANITIZER_INTERCEPT_SETLOCALE SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_GETCWD SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX_NOT_ANDROID @@ -220,7 +220,7 @@ // FIXME: getline seems to be available on OSX 10.7 #define SANITIZER_INTERCEPT_GETLINE SI_FREEBSD || SI_LINUX_NOT_ANDROID -#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD +#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD || SI_MAC #define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \ diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 9cfaec5cc8..7aebc9c00b 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -119,8 +119,11 @@ #if SANITIZER_LINUX || SANITIZER_FREEBSD # include # include -# if defined(__mips64) || defined(__aarch64__) +# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) # include +# ifdef __arm__ +typedef struct user_fpregs elf_fpregset_t; +# endif # endif # include #endif @@ -304,8 +307,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) -#if defined(__mips64) || defined(__powerpc64__) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) +#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__) unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs); unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t); #elif defined(__aarch64__) @@ -316,11 +319,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct); #endif // __mips64 || __powerpc64__ || __aarch64__ #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \ - defined(__aarch64__) + defined(__aarch64__) || defined(__arm__) unsigned struct_user_fpxregs_struct_sz = 0; #else unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); -#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ +#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__ +#ifdef __arm__ + unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; +#else + unsigned struct_user_vfpregs_struct_sz = 0; +#endif int ptrace_peektext = PTRACE_PEEKTEXT; int ptrace_peekdata = PTRACE_PEEKDATA; @@ -346,6 +354,13 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); int ptrace_getfpxregs = -1; int ptrace_setfpxregs = -1; #endif // PTRACE_GETFPXREGS/PTRACE_SETFPXREGS +#if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS) + int ptrace_getvfpregs = PTRACE_GETVFPREGS; + int ptrace_setvfpregs = PTRACE_SETVFPREGS; +#else + int ptrace_getvfpregs = -1; + int ptrace_setvfpregs = -1; +#endif int ptrace_geteventmsg = PTRACE_GETEVENTMSG; #if (defined(PTRACE_GETSIGINFO) && defined(PTRACE_SETSIGINFO)) || \ (defined(PT_GETSIGINFO) && defined(PT_SETSIGINFO)) diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index c598fe0d71..2978e7b9ce 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -736,10 +736,11 @@ namespace __sanitizer { #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) extern unsigned struct_user_regs_struct_sz; extern unsigned struct_user_fpregs_struct_sz; extern unsigned struct_user_fpxregs_struct_sz; + extern unsigned struct_user_vfpregs_struct_sz; extern int ptrace_peektext; extern int ptrace_peekdata; @@ -750,6 +751,8 @@ namespace __sanitizer { extern int ptrace_setfpregs; extern int ptrace_getfpxregs; extern int ptrace_setfpxregs; + extern int ptrace_getvfpregs; + extern int ptrace_setvfpregs; extern int ptrace_getsiginfo; extern int ptrace_setsiginfo; extern int ptrace_getregset; diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index d61fee1fc5..9ad66bec2a 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -119,7 +119,7 @@ void *MmapOrDie(uptr size, const char *mem_type) { MAP_PRIVATE | MAP_ANON, -1, 0); int reserrno; if (internal_iserror(res, &reserrno)) - ReportMmapFailureAndDie(size, mem_type, reserrno); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); IncreaseTotalMmap(size); return (void *)res; } @@ -143,12 +143,8 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) { MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); int reserrno; - if (internal_iserror(p, &reserrno)) { - Report("ERROR: %s failed to " - "allocate noreserve 0x%zx (%zd) bytes for '%s' (errno: %d)\n", - SanitizerToolName, size, size, mem_type, reserrno); - CHECK("unable to mmap" && 0); - } + if (internal_iserror(p, &reserrno)) + ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno); IncreaseTotalMmap(size); return (void *)p; } @@ -162,10 +158,10 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) { -1, 0); int reserrno; if (internal_iserror(p, &reserrno)) { - Report("ERROR: %s failed to " - "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n", - SanitizerToolName, size, size, fixed_addr, reserrno); - CHECK("unable to mmap" && 0); + char mem_type[30]; + internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx", + fixed_addr); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); } IncreaseTotalMmap(size); return (void *)p; diff --git a/lib/sanitizer_common/sanitizer_posix.h b/lib/sanitizer_common/sanitizer_posix.h index 5a9e97d5b5..19fa505c52 100644 --- a/lib/sanitizer_common/sanitizer_posix.h +++ b/lib/sanitizer_common/sanitizer_posix.h @@ -74,6 +74,8 @@ int real_pthread_join(void *th, void **ret); } \ } // namespace __sanitizer +int my_pthread_attr_getstack(void *attr, void **addr, uptr *size); + int internal_sigaction(int signum, const void *act, void *oldact); } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index b67a779b90..d7b9f20414 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -276,6 +276,49 @@ void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) { return (void *)internal_mmap((void *)fixed_addr, size, PROT_NONE, flags, fd, 0); } + +// This function is defined elsewhere if we intercepted pthread_attr_getstack. +extern "C" { +SANITIZER_WEAK_ATTRIBUTE int +real_pthread_attr_getstack(void *attr, void **addr, size_t *size); +} // extern "C" + +int my_pthread_attr_getstack(void *attr, void **addr, uptr *size) { +#if !SANITIZER_GO && !SANITIZER_MAC + if (&real_pthread_attr_getstack) + return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, + (size_t *)size); +#endif + return pthread_attr_getstack((pthread_attr_t *)attr, addr, (size_t *)size); +} + +#if !SANITIZER_GO +void AdjustStackSize(void *attr_) { + pthread_attr_t *attr = (pthread_attr_t *)attr_; + uptr stackaddr = 0; + uptr stacksize = 0; + my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); + // GLibC will return (0 - stacksize) as the stack address in the case when + // stacksize is set, but stackaddr is not. + bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); + // We place a lot of tool data into TLS, account for that. + const uptr minstacksize = GetTlsSize() + 128*1024; + if (stacksize < minstacksize) { + if (!stack_set) { + if (stacksize != 0) { + VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, + minstacksize); + pthread_attr_setstacksize(attr, minstacksize); + } + } else { + Printf("Sanitizer: pre-allocated stack size is insufficient: " + "%zu < %zu\n", stacksize, minstacksize); + Printf("Sanitizer: pthread_create is likely to fail.\n"); + } + } +} +#endif // !SANITIZER_GO + } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index 0ed236a0f3..a19b0a6786 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -446,14 +446,16 @@ static void ChooseSymbolizerTools(IntrusiveList *list, if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) { list->push_back(tool); - } else { - VReport(2, "No internal or external symbolizer found.\n"); } #if SANITIZER_MAC VReport(2, "Using dladdr symbolizer.\n"); list->push_back(new(*allocator) DlAddrSymbolizer()); #endif // SANITIZER_MAC + + if (list->size() == 0) { + Report("WARNING: no internal or external symbolizer found.\n"); + } } Symbolizer *Symbolizer::PlatformInit() { diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc index b6aa6ca374..b1dceebf45 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -14,6 +14,7 @@ #include "sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN #include #include #pragma comment(lib, "dbghelp.lib") diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index dca5a6da1c..bcebce0b29 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -86,7 +86,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, void *MmapOrDie(uptr size, const char *mem_type) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) - ReportMmapFailureAndDie(size, mem_type, GetLastError()); + ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); return rv; } diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index 2f246d42b4..cbfca5ce28 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -26,6 +26,7 @@ set(TSAN_SOURCES rtl/tsan_interface_atomic.cc rtl/tsan_interface.cc rtl/tsan_interface_java.cc + rtl/tsan_malloc_mac.cc rtl/tsan_md5.cc rtl/tsan_mman.cc rtl/tsan_mutex.cc @@ -45,11 +46,14 @@ set(TSAN_CXX_SOURCES rtl/tsan_new_delete.cc) if(APPLE) - list(APPEND TSAN_SOURCES rtl/tsan_platform_mac.cc) + list(APPEND TSAN_SOURCES + rtl/tsan_platform_mac.cc + rtl/tsan_platform_posix.cc) elseif(UNIX) # Assume Linux list(APPEND TSAN_SOURCES - rtl/tsan_platform_linux.cc) + rtl/tsan_platform_linux.cc + rtl/tsan_platform_posix.cc) endif() set(TSAN_HEADERS @@ -83,52 +87,66 @@ set(TSAN_HEADERS set(TSAN_RUNTIME_LIBRARIES) add_custom_target(tsan) -foreach(arch ${TSAN_SUPPORTED_ARCH}) - if(arch STREQUAL "x86_64") - set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) - # Pass ASM file directly to the C++ compiler. - set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES - LANGUAGE C) - # Sanity check for Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - else() - set(TSAN_ASM_SOURCES) - endif() +if(APPLE) add_compiler_rt_runtime(clang_rt.tsan - STATIC - ARCHS ${arch} - SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES} - $ - $ - $ - $ - CFLAGS ${TSAN_RTL_CFLAGS}) - add_compiler_rt_runtime(clang_rt.tsan_cxx - STATIC - ARCHS ${arch} - SOURCES ${TSAN_CXX_SOURCES} - $ - CFLAGS ${TSAN_RTL_CFLAGS}) - list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch}) - add_sanitizer_rt_symbols(clang_rt.tsan - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.tsan_cxx - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_dependencies(tsan clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch} - clang_rt.tsan-${arch}-symbols - clang_rt.tsan_cxx-${arch}-symbols) -endforeach() + SHARED + OS ${TSAN_SUPPORTED_OS} + ARCHS ${TSAN_SUPPORTED_ARCH} + SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} + OBJECT_LIBS RTInterception + RTSanitizerCommon + RTSanitizerCommonLibc + RTUbsan + CFLAGS ${TSAN_RTL_CFLAGS} + PARENT_TARGET tsan) +else() + foreach(arch ${TSAN_SUPPORTED_ARCH}) + if(arch STREQUAL "x86_64") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES + LANGUAGE C) + # Sanity check for Go runtime. + set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) + add_custom_target(GotsanRuntimeCheck + COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" + IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} + DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go + COMMENT "Checking TSan Go runtime..." + VERBATIM) + else() + set(TSAN_ASM_SOURCES) + endif() + add_compiler_rt_runtime(clang_rt.tsan + STATIC + ARCHS ${arch} + SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES} + $ + $ + $ + $ + CFLAGS ${TSAN_RTL_CFLAGS}) + add_compiler_rt_runtime(clang_rt.tsan_cxx + STATIC + ARCHS ${arch} + SOURCES ${TSAN_CXX_SOURCES} + $ + CFLAGS ${TSAN_RTL_CFLAGS}) + list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch} + clang_rt.tsan_cxx-${arch}) + add_sanitizer_rt_symbols(clang_rt.tsan + ARCHS ${arch} + EXTRA rtl/tsan.syms.extra) + add_sanitizer_rt_symbols(clang_rt.tsan_cxx + ARCHS ${arch} + EXTRA rtl/tsan.syms.extra) + add_dependencies(tsan clang_rt.tsan-${arch} + clang_rt.tsan_cxx-${arch} + clang_rt.tsan-${arch}-symbols + clang_rt.tsan_cxx-${arch}-symbols) + endforeach() +endif() add_dependencies(compiler-rt tsan) diff --git a/lib/tsan/rtl/tsan_clock.cc b/lib/tsan/rtl/tsan_clock.cc index 59e3de435f..1e2050d1f2 100644 --- a/lib/tsan/rtl/tsan_clock.cc +++ b/lib/tsan/rtl/tsan_clock.cc @@ -90,8 +90,6 @@ namespace __tsan { -const unsigned kInvalidTid = (unsigned)-1; - ThreadClock::ThreadClock(unsigned tid, unsigned reused) : tid_(tid) , reused_(reused + 1) { // 0 has special meaning diff --git a/lib/tsan/rtl/tsan_clock.h b/lib/tsan/rtl/tsan_clock.h index fd6509335f..4e352cb81d 100644 --- a/lib/tsan/rtl/tsan_clock.h +++ b/lib/tsan/rtl/tsan_clock.h @@ -33,7 +33,8 @@ struct ClockBlock { ClockElem clock[kClockCount]; }; - ClockBlock() = default; + ClockBlock() { + } }; typedef DenseSlabAlloc ClockAlloc; diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h index d869d95e08..385e366c39 100644 --- a/lib/tsan/rtl/tsan_defs.h +++ b/lib/tsan/rtl/tsan_defs.h @@ -83,6 +83,8 @@ const bool kCollectHistory = false; const bool kCollectHistory = true; #endif +const unsigned kInvalidTid = (unsigned)-1; + // The following "build consistency" machinery ensures that all source files // are built in the same configuration. Inconsistent builds lead to // hard to debug crashes. diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index c0864218e0..800c7bd98b 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -28,16 +28,28 @@ #include "tsan_mman.h" #include "tsan_fd.h" +#if SANITIZER_POSIX +#include "sanitizer_common/sanitizer_posix.h" +#endif + using namespace __tsan; // NOLINT -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC #define __errno_location __error -#define __libc_realloc __realloc -#define __libc_calloc __calloc #define stdout __stdoutp #define stderr __stderrp #endif +#if SANITIZER_FREEBSD +#define __libc_realloc __realloc +#define __libc_calloc __calloc +#elif SANITIZER_MAC +#define __libc_malloc REAL(malloc) +#define __libc_realloc REAL(realloc) +#define __libc_calloc REAL(calloc) +#define __libc_free REAL(free) +#endif + #if SANITIZER_LINUX || SANITIZER_FREEBSD #define PTHREAD_CREATE_DETACHED 1 #elif SANITIZER_MAC @@ -80,12 +92,13 @@ extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); extern "C" int pthread_setspecific(unsigned key, const void *v); DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) -extern "C" int pthread_yield(); extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); // REAL(sigfillset) defined in common interceptors. DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) DECLARE_REAL(int, fflush, __sanitizer_FILE *fp) +DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size) +DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int *__errno_location(); @@ -102,7 +115,9 @@ const int PTHREAD_MUTEX_RECURSIVE_NP = 1; const int EINVAL = 22; const int EBUSY = 16; const int EOWNERDEAD = 130; +#if !SANITIZER_MAC const int EPOLL_CTL_ADD = 1; +#endif const int SIGILL = 4; const int SIGABRT = 6; const int SIGFPE = 8; @@ -117,7 +132,9 @@ const int SIGBUS = 7; const int SIGSYS = 31; #endif void *const MAP_FAILED = (void*)-1; +#if !SANITIZER_MAC const int PTHREAD_BARRIER_SERIAL_THREAD = -1; +#endif const int MAP_FIXED = 0x10; typedef long long_t; // NOLINT @@ -372,6 +389,7 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), return res; } +#if !SANITIZER_MAC static void on_exit_wrapper(int status, void *arg) { ThreadState *thr = cur_thread(); uptr pc = 0; @@ -396,6 +414,7 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { ThreadIgnoreEnd(thr, pc); return res; } +#endif // Cleanup old bufs. static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { @@ -519,6 +538,7 @@ TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { REAL(siglongjmp)(env, val); } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, malloc, uptr size) { if (cur_thread()->in_symbolizer) return __libc_malloc(size); @@ -585,6 +605,7 @@ TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); return user_alloc_usable_size(p); } +#endif TSAN_INTERCEPTOR(uptr, strlen, const char *s) { SCOPED_TSAN_INTERCEPTOR(strlen, s); @@ -609,13 +630,18 @@ TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) { MemoryAccessRange(thr, pc, (uptr)dst, size, true); MemoryAccessRange(thr, pc, (uptr)src, size, false); } - return internal_memcpy(dst, src, size); + // On OS X, calling internal_memcpy here will cause memory corruptions, + // because memcpy and memmove are actually aliases of the same implementation. + // We need to use internal_memmove here. + return internal_memmove(dst, src, size); } TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) { - SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n); - MemoryAccessRange(thr, pc, (uptr)dst, n, true); - MemoryAccessRange(thr, pc, (uptr)src, n, false); + if (!COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { + SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n); + MemoryAccessRange(thr, pc, (uptr)dst, n, true); + MemoryAccessRange(thr, pc, (uptr)src, n, false); + } return REAL(memmove)(dst, src, n); } @@ -628,6 +654,7 @@ TSAN_INTERCEPTOR(char*, strchr, char *s, int c) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c); char *res = REAL(strchrnul)(s, c); @@ -635,6 +662,7 @@ TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { READ_STRING(thr, pc, s, len); return res; } +#endif TSAN_INTERCEPTOR(char*, strrchr, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strrchr, s, c); @@ -678,8 +706,8 @@ static bool fix_mmap_addr(void **addr, long_t sz, int flags) { return true; } -TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, - int flags, int fd, unsigned off) { +TSAN_INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF_T off) { SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off); if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; @@ -692,9 +720,9 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, return res; } -#if !SANITIZER_FREEBSD -TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, - int flags, int fd, u64 off) { +#if SANITIZER_LINUX +TSAN_INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF64_T off) { SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; @@ -722,7 +750,7 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -732,6 +760,7 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { #define TSAN_MAYBE_INTERCEPT_MEMALIGN #endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -741,8 +770,9 @@ TSAN_INTERCEPTOR(void*, valloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } +#endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(pvalloc, sz); sz = RoundUp(sz, GetPageSizeCached()); @@ -753,11 +783,13 @@ TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { #define TSAN_MAYBE_INTERCEPT_PVALLOC #endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz); *memptr = user_alloc(thr, pc, sz, align); return 0; } +#endif // Used in thread-safe function static initialization. extern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) { @@ -787,6 +819,19 @@ extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) { atomic_store(g, 0, memory_order_relaxed); } +namespace __tsan { +void DestroyThreadState() { + ThreadState *thr = cur_thread(); + ThreadFinish(thr); + ThreadSignalContext *sctx = thr->signal_ctx; + if (sctx) { + thr->signal_ctx = 0; + UnmapOrDie(sctx, sizeof(*sctx)); + } + cur_thread_finalize(); +} +} // namespace __tsan + static void thread_finalize(void *v) { uptr iter = (uptr)v; if (iter > 1) { @@ -796,15 +841,7 @@ static void thread_finalize(void *v) { } return; } - { - ThreadState *thr = cur_thread(); - ThreadFinish(thr); - ThreadSignalContext *sctx = thr->signal_ctx; - if (sctx) { - thr->signal_ctx = 0; - UnmapOrDie(sctx, sizeof(*sctx)); - } - } + DestroyThreadState(); } @@ -831,7 +868,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { } ThreadIgnoreEnd(thr, 0); while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) - pthread_yield(); + internal_sched_yield(); ThreadStart(thr, tid, GetTid()); atomic_store(&p->tid, 0, memory_order_release); } @@ -891,7 +928,7 @@ TSAN_INTERCEPTOR(int, pthread_create, // before the new thread got a chance to acquire from it in ThreadStart. atomic_store(&p.tid, tid, memory_order_release); while (atomic_load(&p.tid, memory_order_acquire) != 0) - pthread_yield(); + internal_sched_yield(); } if (attr == &myattr) pthread_attr_destroy(&myattr); @@ -1094,6 +1131,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime); int res = REAL(pthread_mutex_timedlock)(m, abstime); @@ -1102,7 +1140,9 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } return res; } +#endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); int res = REAL(pthread_spin_init)(m, pshared); @@ -1145,6 +1185,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) { int res = REAL(pthread_spin_unlock)(m); return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a); @@ -1182,6 +1223,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime); int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); @@ -1190,6 +1232,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); @@ -1209,6 +1252,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime); int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); @@ -1217,6 +1261,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m); @@ -1225,6 +1270,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) { SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count); MemoryWrite(thr, pc, (uptr)b, kSizeLog1); @@ -1250,12 +1296,17 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); if (o == 0 || f == 0) return EINVAL; - atomic_uint32_t *a = static_cast(o); + atomic_uint32_t *a; + if (!SANITIZER_MAC) + a = static_cast(o); + else // On OS X, pthread_once_t has a header with a long-sized signature. + a = static_cast((void *)((char *)o + sizeof(long_t))); u32 v = atomic_load(a, memory_order_acquire); if (v == 0 && atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) { @@ -1265,7 +1316,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { atomic_store(a, 2, memory_order_release); } else { while (v != 2) { - pthread_yield(); + internal_sched_yield(); v = atomic_load(a, memory_order_acquire); } if (!thr->in_ignored_lib) @@ -1274,7 +1325,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1286,7 +1337,7 @@ TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1297,7 +1348,7 @@ TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1308,7 +1359,7 @@ TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1319,7 +1370,7 @@ TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1331,7 +1382,7 @@ TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1342,7 +1393,7 @@ TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1353,7 +1404,7 @@ TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1364,7 +1415,7 @@ TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1377,7 +1428,7 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1390,7 +1441,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1402,7 +1453,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1423,7 +1474,7 @@ TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); READ_STRING(thr, pc, name, 0); @@ -1446,7 +1497,7 @@ TSAN_INTERCEPTOR(int, creat, const char *name, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) { SCOPED_TSAN_INTERCEPTOR(creat64, name, mode); READ_STRING(thr, pc, name, 0); @@ -1476,6 +1527,7 @@ TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) { return newfd2; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags); int newfd2 = REAL(dup3)(oldfd, newfd, flags); @@ -1483,8 +1535,9 @@ TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { FdDup(thr, pc, oldfd, newfd2, false); return newfd2; } +#endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags); int fd = REAL(eventfd)(initval, flags); @@ -1497,7 +1550,7 @@ TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { #define TSAN_MAYBE_INTERCEPT_EVENTFD #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags); if (fd >= 0) @@ -1512,7 +1565,7 @@ TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { #define TSAN_MAYBE_INTERCEPT_SIGNALFD #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, inotify_init, int fake) { SCOPED_TSAN_INTERCEPTOR(inotify_init, fake); int fd = REAL(inotify_init)(fake); @@ -1525,7 +1578,7 @@ TSAN_INTERCEPTOR(int, inotify_init, int fake) { #define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, inotify_init1, int flags) { SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags); int fd = REAL(inotify_init1)(flags); @@ -1579,7 +1632,7 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_create, int size) { SCOPED_TSAN_INTERCEPTOR(epoll_create, size); int fd = REAL(epoll_create)(size); @@ -1592,7 +1645,7 @@ TSAN_INTERCEPTOR(int, epoll_create, int size) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_create1, int flags) { SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags); int fd = REAL(epoll_create1)(flags); @@ -1612,7 +1665,7 @@ TSAN_INTERCEPTOR(int, close, int fd) { return REAL(close)(fd); } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __close, int fd) { SCOPED_TSAN_INTERCEPTOR(__close, fd); if (fd >= 0) @@ -1625,7 +1678,7 @@ TSAN_INTERCEPTOR(int, __close, int fd) { #endif // glibc guts -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1649,6 +1702,7 @@ TSAN_INTERCEPTOR(int, pipe, int *pipefd) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags); int res = REAL(pipe2)(pipefd, flags); @@ -1656,6 +1710,7 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); return res; } +#endif TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); @@ -1706,7 +1761,7 @@ TSAN_INTERCEPTOR(void*, tmpfile, int fake) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, tmpfile64, int fake) { SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake); void *res = REAL(tmpfile64)(fake); @@ -1773,7 +1828,7 @@ TSAN_INTERCEPTOR(int, closedir, void *dirp) { return REAL(closedir)(dirp); } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev); if (epfd >= 0) @@ -1790,7 +1845,7 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CTL #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); if (epfd >= 0) @@ -2089,6 +2144,7 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } +#if !SANITIZER_MAC typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2132,6 +2188,7 @@ TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) { int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata); return res; } +#endif static int OnExit(ThreadState *thr) { int status = Finalize(thr); @@ -2145,6 +2202,7 @@ struct TsanInterceptorContext { const uptr pc; }; +#if !SANITIZER_MAC static void HandleRecvmsg(ThreadState *thr, uptr pc, __sanitizer_msghdr *msg) { int fds[64]; @@ -2152,6 +2210,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, for (int i = 0; i < cnt; i++) FdEventCreate(thr, pc, fds[i]); } +#endif #include "sanitizer_common/sanitizer_platform_interceptors.h" // Causes interceptor recursion (getaddrinfo() and fopen()) @@ -2266,9 +2325,11 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, (uptr)m) +#if !SANITIZER_MAC #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, msg) +#endif #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (TsanThread *t = GetCurrentThread()) { \ @@ -2300,6 +2361,7 @@ struct ScopedSyscall { } }; +#if !SANITIZER_MAC static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { TSAN_SYSCALL(); MemoryAccessRange(thr, pc, p, s, write); @@ -2353,6 +2415,7 @@ static void syscall_post_fork(uptr pc, int pid) { ForkParentAfter(thr, pc); } } +#endif #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false) @@ -2403,24 +2466,29 @@ static void finalize(void *arg) { Die(); } +#if !SANITIZER_MAC static void unreachable() { Report("FATAL: ThreadSanitizer: unreachable called\n"); Die(); } +#endif void InitializeInterceptors() { +#if !SANITIZER_MAC // We need to setup it early, because functions like dlsym() can call it. REAL(memset) = internal_memset; REAL(memcpy) = internal_memcpy; +#endif // Instruct libc malloc to consume less memory. -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX mallopt(1, 0); // M_MXFAST mallopt(-3, 32*1024); // M_MMAP_THRESHOLD #endif InitializeCommonInterceptors(); +#if !SANITIZER_MAC // We can not use TSAN_INTERCEPT to get setjmp addr, // because it does &setjmp and setjmp is not present in some versions of libc. using __interception::GetRealFunctionAddress; @@ -2428,6 +2496,7 @@ void InitializeInterceptors() { GetRealFunctionAddress("_setjmp", (uptr*)&REAL(_setjmp), 0, 0); GetRealFunctionAddress("sigsetjmp", (uptr*)&REAL(sigsetjmp), 0, 0); GetRealFunctionAddress("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0); +#endif TSAN_INTERCEPT(longjmp); TSAN_INTERCEPT(siglongjmp); @@ -2567,9 +2636,12 @@ void InitializeInterceptors() { TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); +#if !SANITIZER_MAC // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; +#endif + if (REAL(__cxa_atexit)(&finalize, 0, 0)) { Printf("ThreadSanitizer: failed to setup atexit callback\n"); Die(); diff --git a/lib/tsan/rtl/tsan_malloc_mac.cc b/lib/tsan/rtl/tsan_malloc_mac.cc new file mode 100644 index 0000000000..6319fdf603 --- /dev/null +++ b/lib/tsan/rtl/tsan_malloc_mac.cc @@ -0,0 +1,59 @@ +//===-- tsan_malloc_mac.cc ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific malloc interception. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_MAC + +#include "tsan_interceptors.h" +#include "tsan_stack_trace.h" + +using namespace __tsan; +#define COMMON_MALLOC_ZONE_NAME "tsan" +#define COMMON_MALLOC_ENTER() +#define COMMON_MALLOC_SANITIZER_INITIALIZED (cur_thread()->is_inited) +#define COMMON_MALLOC_FORCE_LOCK() +#define COMMON_MALLOC_FORCE_UNLOCK() +#define COMMON_MALLOC_MEMALIGN(alignment, size) \ + void *p = \ + user_alloc(cur_thread(), StackTrace::GetCurrentPc(), size, alignment) +#define COMMON_MALLOC_MALLOC(size) \ + SCOPED_INTERCEPTOR_RAW(malloc, size); \ + void *p = user_alloc(thr, pc, size) +#define COMMON_MALLOC_REALLOC(ptr, size) \ + SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \ + void *p = user_realloc(thr, pc, ptr, size); +#define COMMON_MALLOC_CALLOC(count, size) \ + SCOPED_INTERCEPTOR_RAW(calloc, size, count); \ + void *p = user_calloc(thr, pc, size, count); +#define COMMON_MALLOC_VALLOC(size) \ + SCOPED_INTERCEPTOR_RAW(valloc, size); \ + void *p = user_alloc(thr, pc, size, GetPageSizeCached()); +#define COMMON_MALLOC_FREE(ptr) \ + SCOPED_INTERCEPTOR_RAW(free, ptr); \ + user_free(thr, pc, ptr); +#define COMMON_MALLOC_SIZE(ptr) \ + uptr size = user_alloc_usable_size(ptr); +#define COMMON_MALLOC_FILL_STATS(zone, stats) +#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr); +#define COMMON_MALLOC_IGNORE_INVALID_FREE false +#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("free_common(%p) -- attempting to free unallocated memory.\n", ptr); +#define COMMON_MALLOC_NAMESPACE __tsan + +#include "sanitizer_common/sanitizer_malloc_mac.inc" + +#endif diff --git a/lib/tsan/rtl/tsan_mman.h b/lib/tsan/rtl/tsan_mman.h index 5ff956d827..b419b58ca4 100644 --- a/lib/tsan/rtl/tsan_mman.h +++ b/lib/tsan/rtl/tsan_mman.h @@ -20,6 +20,7 @@ namespace __tsan { const uptr kDefaultAlignment = 16; void InitializeAllocator(); +void ReplaceSystemMalloc(); void AllocatorThreadStart(ThreadState *thr); void AllocatorThreadFinish(ThreadState *thr); void AllocatorPrintStats(); diff --git a/lib/tsan/rtl/tsan_mutex.cc b/lib/tsan/rtl/tsan_mutex.cc index e18f6fa70c..9dd24803b1 100644 --- a/lib/tsan/rtl/tsan_mutex.cc +++ b/lib/tsan/rtl/tsan_mutex.cc @@ -126,8 +126,9 @@ void InitializeMutex() { #endif } -// Rely on zero initialization because some mutexes can be locked before ctor. -InternalDeadlockDetector::InternalDeadlockDetector() = default; +InternalDeadlockDetector::InternalDeadlockDetector() { + // Rely on zero initialization because some mutexes can be locked before ctor. +} #if SANITIZER_DEBUG && !SANITIZER_GO void InternalDeadlockDetector::Lock(MutexType t) { diff --git a/lib/tsan/rtl/tsan_new_delete.cc b/lib/tsan/rtl/tsan_new_delete.cc index d3ac472b7d..18ba9082c4 100644 --- a/lib/tsan/rtl/tsan_new_delete.cc +++ b/lib/tsan/rtl/tsan_new_delete.cc @@ -12,6 +12,7 @@ // Interceptors for operators new and delete. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_internal_defs.h" +#include "interception/interception.h" #include "tsan_interceptors.h" using namespace __tsan; // NOLINT @@ -20,6 +21,13 @@ namespace std { struct nothrow_t {}; } // namespace std +DECLARE_REAL(void *, malloc, uptr size) +DECLARE_REAL(void, free, void *ptr) +#if SANITIZER_MAC +#define __libc_malloc REAL(malloc) +#define __libc_free REAL(free) +#endif + #define OPERATOR_NEW_BODY(mangled_name) \ if (cur_thread()->in_symbolizer) \ return __libc_malloc(size); \ diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index dcf9d64c32..57cd86d830 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -340,6 +340,8 @@ uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { } void InitializePlatform(); +void CheckAndProtect(); +void InitializeShadowMemoryPlatform(); void FlushShadowMemory(); void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); @@ -353,6 +355,8 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, void *abstime), void *c, void *m, void *abstime, void(*cleanup)(void *arg), void *arg); +void DestroyThreadState(); + } // namespace __tsan #endif // TSAN_PLATFORM_H diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 51637ad808..f6c704051c 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -132,17 +132,6 @@ void FlushShadowMemory() { } #ifndef SANITIZER_GO -static void ProtectRange(uptr beg, uptr end) { - CHECK_LE(beg, end); - if (beg == end) - return; - if (beg != (uptr)MmapNoAccess(beg, end - beg)) { - Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); - Printf("FATAL: Make sure you are not using unlimited stack\n"); - Die(); - } -} - // Mark shadow for .rodata sections with the special kShadowRodata marker. // Accesses to .rodata can't race, so this saves time, memory and trace space. static void MapRodata() { @@ -200,58 +189,7 @@ static void MapRodata() { internal_close(fd); } -void InitializeShadowMemory() { - // Map memory shadow. - uptr shadow = - (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow"); - if (shadow != kShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", shadow, kShadowBeg); - Die(); - } - // This memory range is used for thread stacks and large user mmaps. - // Frequently a thread uses only a small part of stack and similarly - // a program uses a small part of large mmap. On some programs - // we see 20% memory usage reduction without huge pages for this range. - // FIXME: don't use constants here. -#if defined(__x86_64__) - const uptr kMadviseRangeBeg = 0x7f0000000000ull; - const uptr kMadviseRangeSize = 0x010000000000ull; -#elif defined(__mips64) - const uptr kMadviseRangeBeg = 0xff00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; -#elif defined(__aarch64__) - const uptr kMadviseRangeBeg = 0x7e00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; -#endif - NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), - kMadviseRangeSize * kShadowMultiplier); - // Meta shadow is compressing and we don't flush it, - // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. - // On one program it reduces memory consumption from 5GB to 2.5GB. - NoHugePagesInRegion(kMetaShadowBeg, kMetaShadowEnd - kMetaShadowBeg); - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); - DPrintf("memory shadow: %zx-%zx (%zuGB)\n", - kShadowBeg, kShadowEnd, - (kShadowEnd - kShadowBeg) >> 30); - - // Map meta shadow. - uptr meta_size = kMetaShadowEnd - kMetaShadowBeg; - uptr meta = - (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow"); - if (meta != kMetaShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", meta, kMetaShadowBeg); - Die(); - } - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(meta, meta_size); - DPrintf("meta shadow: %zx-%zx (%zuGB)\n", - meta, meta + meta_size, meta_size >> 30); - +void InitializeShadowMemoryPlatform() { MapRodata(); } @@ -295,31 +233,6 @@ static void InitDataSeg() { CHECK_LT((uptr)&g_data_start, g_data_end); } -static void CheckAndProtect() { - // Ensure that the binary is indeed compiled with -pie. - MemoryMappingLayout proc_maps(true); - uptr p, end; - while (proc_maps.Next(&p, &end, 0, 0, 0, 0)) { - if (IsAppMem(p)) - continue; - if (p >= kHeapMemEnd && - p < HeapEnd()) - continue; - if (p >= kVdsoBeg) // vdso - break; - Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); - Die(); - } - - ProtectRange(kLoAppMemEnd, kShadowBeg); - ProtectRange(kShadowEnd, kMetaShadowBeg); - ProtectRange(kMetaShadowEnd, kTraceMemBeg); - // Memory for traces is mapped lazily in MapThreadTrace. - // Protect the whole range for now, so that user does not map something here. - ProtectRange(kTraceMemBeg, kTraceMemEnd); - ProtectRange(kTraceMemEnd, kHeapMemBeg); - ProtectRange(HeapEnd(), kHiAppMemBeg); -} #endif // #ifndef SANITIZER_GO void InitializePlatform() { @@ -418,6 +331,10 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif +#ifndef SANITIZER_GO +void ReplaceSystemMalloc() { } +#endif + } // namespace __tsan #endif // SANITIZER_LINUX || SANITIZER_FREEBSD diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index b72d9b07ef..446d790019 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -15,8 +15,10 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC +#include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" #include "tsan_platform.h" #include "tsan_rtl.h" @@ -40,6 +42,62 @@ namespace __tsan { +static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) { + atomic_uintptr_t *a = (atomic_uintptr_t *)dst; + void *val = (void *)atomic_load_relaxed(a); + atomic_signal_fence(memory_order_acquire); // Turns the previous load into + // acquire wrt signals. + if (UNLIKELY(val == nullptr)) { + val = (void *)internal_mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + CHECK(val); + void *cmp = nullptr; + if (!atomic_compare_exchange_strong(a, (uintptr_t *)&cmp, (uintptr_t)val, + memory_order_acq_rel)) { + internal_munmap(val, size); + val = cmp; + } + } + return val; +} + +#ifndef SANITIZER_GO +// On OS X, accessing TLVs via __thread or manually by using pthread_key_* is +// problematic, because there are several places where interceptors are called +// when TLVs are not accessible (early process startup, thread cleanup, ...). +// The following provides a "poor man's TLV" implementation, where we use the +// shadow memory of the pointer returned by pthread_self() to store a pointer to +// the ThreadState object. The main thread's ThreadState pointer is stored +// separately in a static variable, because we need to access it even before the +// shadow memory is set up. +static uptr main_thread_identity = 0; +static ThreadState *main_thread_state = nullptr; + +ThreadState *cur_thread() { + ThreadState **fake_tls; + uptr thread_identity = (uptr)pthread_self(); + if (thread_identity == main_thread_identity || main_thread_identity == 0) { + fake_tls = &main_thread_state; + } else { + fake_tls = (ThreadState **)MemToShadow(thread_identity); + } + ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate( + (uptr *)fake_tls, sizeof(ThreadState)); + return thr; +} + +// TODO(kuba.brecka): This is not async-signal-safe. In particular, we call +// munmap first and then clear `fake_tls`; if we receive a signal in between, +// handler will try to access the unmapped ThreadState. +void cur_thread_finalize() { + uptr thread_identity = (uptr)pthread_self(); + CHECK_NE(thread_identity, main_thread_identity); + ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity); + internal_munmap(*fake_tls, sizeof(ThreadState)); + *fake_tls = nullptr; +} +#endif + uptr GetShadowMemoryConsumption() { return 0; } @@ -51,28 +109,57 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { } #ifndef SANITIZER_GO -void InitializeShadowMemory() { - uptr shadow = (uptr)MmapFixedNoReserve(kShadowBeg, - kShadowEnd - kShadowBeg); - if (shadow != kShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie.\n"); - Die(); +void InitializeShadowMemoryPlatform() { } +#endif + +// On OS X, GCD worker threads are created without a call to pthread_create. We +// need to properly register these threads with ThreadCreate and ThreadStart. +// These threads don't have a parent thread, as they are created "spuriously". +// We're using a libpthread API that notifies us about a newly created thread. +// The `thread == pthread_self()` check indicates this is actually a worker +// thread. If it's just a regular thread, this hook is called on the parent +// thread. +typedef void (*pthread_introspection_hook_t)(unsigned int event, + pthread_t thread, void *addr, + size_t size); +extern "C" pthread_introspection_hook_t pthread_introspection_hook_install( + pthread_introspection_hook_t hook); +static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1; +static const uptr PTHREAD_INTROSPECTION_THREAD_DESTROY = 4; +static pthread_introspection_hook_t prev_pthread_introspection_hook; +static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, + void *addr, size_t size) { + if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) { + if (thread == pthread_self()) { + // The current thread is a newly created GCD worker thread. + ThreadState *parent_thread_state = nullptr; // No parent. + int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true); + CHECK_NE(tid, 0); + ThreadState *thr = cur_thread(); + ThreadStart(thr, tid, GetTid()); + } + } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) { + ThreadState *thr = cur_thread(); + if (thr->tctx->parent_tid == kInvalidTid) { + DestroyThreadState(); + } } - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); - DPrintf("kShadow %zx-%zx (%zuGB)\n", - kShadowBeg, kShadowEnd, - (kShadowEnd - kShadowBeg) >> 30); - DPrintf("kAppMem %zx-%zx (%zuGB)\n", - kAppMemBeg, kAppMemEnd, - (kAppMemEnd - kAppMemBeg) >> 30); + + if (prev_pthread_introspection_hook != nullptr) + prev_pthread_introspection_hook(event, thread, addr, size); } -#endif void InitializePlatform() { DisableCoreDumperIfNecessary(); +#ifndef SANITIZER_GO + CheckAndProtect(); + + CHECK_EQ(main_thread_identity, 0); + main_thread_identity = (uptr)pthread_self(); +#endif + + prev_pthread_introspection_hook = + pthread_introspection_hook_install(&my_pthread_introspection_hook); } #ifndef SANITIZER_GO @@ -91,6 +178,10 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif +bool IsGlobalVar(uptr addr) { + return false; +} + } // namespace __tsan #endif // SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_platform_posix.cc b/lib/tsan/rtl/tsan_platform_posix.cc new file mode 100644 index 0000000000..1782bf1407 --- /dev/null +++ b/lib/tsan/rtl/tsan_platform_posix.cc @@ -0,0 +1,124 @@ +//===-- tsan_platform_posix.cc --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// POSIX-specific code. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_POSIX + +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_procmaps.h" +#include "tsan_platform.h" +#include "tsan_rtl.h" + +namespace __tsan { + +#ifndef SANITIZER_GO +void InitializeShadowMemory() { + // Map memory shadow. + uptr shadow = + (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow"); + if (shadow != kShadowBeg) { + Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); + Printf("FATAL: Make sure to compile with -fPIE and " + "to link with -pie (%p, %p).\n", shadow, kShadowBeg); + Die(); + } + // This memory range is used for thread stacks and large user mmaps. + // Frequently a thread uses only a small part of stack and similarly + // a program uses a small part of large mmap. On some programs + // we see 20% memory usage reduction without huge pages for this range. + // FIXME: don't use constants here. +#if defined(__x86_64__) + const uptr kMadviseRangeBeg = 0x7f0000000000ull; + const uptr kMadviseRangeSize = 0x010000000000ull; +#elif defined(__mips64) + const uptr kMadviseRangeBeg = 0xff00000000ull; + const uptr kMadviseRangeSize = 0x0100000000ull; +#elif defined(__aarch64__) + const uptr kMadviseRangeBeg = 0x7e00000000ull; + const uptr kMadviseRangeSize = 0x0100000000ull; +#endif + NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), + kMadviseRangeSize * kShadowMultiplier); + // Meta shadow is compressing and we don't flush it, + // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. + // On one program it reduces memory consumption from 5GB to 2.5GB. + NoHugePagesInRegion(kMetaShadowBeg, kMetaShadowEnd - kMetaShadowBeg); + if (common_flags()->use_madv_dontdump) + DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); + DPrintf("memory shadow: %zx-%zx (%zuGB)\n", + kShadowBeg, kShadowEnd, + (kShadowEnd - kShadowBeg) >> 30); + + // Map meta shadow. + uptr meta_size = kMetaShadowEnd - kMetaShadowBeg; + uptr meta = + (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow"); + if (meta != kMetaShadowBeg) { + Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); + Printf("FATAL: Make sure to compile with -fPIE and " + "to link with -pie (%p, %p).\n", meta, kMetaShadowBeg); + Die(); + } + if (common_flags()->use_madv_dontdump) + DontDumpShadowMemory(meta, meta_size); + DPrintf("meta shadow: %zx-%zx (%zuGB)\n", + meta, meta + meta_size, meta_size >> 30); + + InitializeShadowMemoryPlatform(); +} + +static void ProtectRange(uptr beg, uptr end) { + CHECK_LE(beg, end); + if (beg == end) + return; + if (beg != (uptr)MmapNoAccess(beg, end - beg)) { + Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); + Printf("FATAL: Make sure you are not using unlimited stack\n"); + Die(); + } +} + +void CheckAndProtect() { + // Ensure that the binary is indeed compiled with -pie. + MemoryMappingLayout proc_maps(true); + uptr p, end, prot; + while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { + if (IsAppMem(p)) + continue; + if (p >= kHeapMemEnd && + p < HeapEnd()) + continue; + if (prot == 0) // Zero page or mprotected. + continue; + if (p >= kVdsoBeg) // vdso + break; + Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); + Die(); + } + + ProtectRange(kLoAppMemEnd, kShadowBeg); + ProtectRange(kShadowEnd, kMetaShadowBeg); + ProtectRange(kMetaShadowEnd, kTraceMemBeg); + // Memory for traces is mapped lazily in MapThreadTrace. + // Protect the whole range for now, so that user does not map something here. + ProtectRange(kTraceMemBeg, kTraceMemEnd); + ProtectRange(kTraceMemEnd, kHeapMemBeg); + ProtectRange(HeapEnd(), kHiAppMemBeg); +} +#endif + +} // namespace __tsan + +#endif // SANITIZER_POSIX diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 9445c409dd..f4b06878a5 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -67,8 +67,9 @@ ReportMop::ReportMop() : mset(MBlockReportMutex) { } -// FIXME(dvyukov): it must be leaking a lot of memory. -ReportDesc::~ReportDesc() = default; +ReportDesc::~ReportDesc() { + // FIXME(dvyukov): it must be leaking a lot of memory. +} #ifndef SANITIZER_GO diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index 24ccc51a21..05d530e982 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -44,7 +44,7 @@ extern "C" void __tsan_resume() { namespace __tsan { -#ifndef SANITIZER_GO +#if !defined(SANITIZER_GO) && !SANITIZER_MAC THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); #endif static char ctx_placeholder[sizeof(Context)] ALIGNED(64); @@ -325,6 +325,7 @@ void Initialize(ThreadState *thr) { CheckVMASize(); #ifndef SANITIZER_GO InitializeAllocator(); + ReplaceSystemMalloc(); #endif InitializeInterceptors(); CheckShadowMapping(); diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index ae44bc9b3b..2e6be3ff06 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -410,12 +410,18 @@ struct ThreadState { }; #ifndef SANITIZER_GO +#if SANITIZER_MAC +ThreadState *cur_thread(); +void cur_thread_finalize(); +#else __attribute__((tls_model("initial-exec"))) extern THREADLOCAL char cur_thread_placeholder[]; INLINE ThreadState *cur_thread() { return reinterpret_cast(&cur_thread_placeholder); } -#endif +INLINE void cur_thread_finalize() { } +#endif // SANITIZER_MAC +#endif // SANITIZER_GO class ThreadContext : public ThreadContextBase { public: @@ -709,7 +715,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); // The trick is that the call preserves all registers and the compiler // does not treat it as a call. // If it does not work for you, use normal call. -#if !SANITIZER_DEBUG && defined(__x86_64__) +#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC // The caller may not create the stack frame for itself at all, // so we create a reserve stack frame for it (1024b must be enough). #define HACKY_CALL(f) \ diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index a167ce1986..dcae255f76 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -31,7 +31,8 @@ ThreadContext::ThreadContext(int tid) } #ifndef SANITIZER_GO -ThreadContext::~ThreadContext() = default; +ThreadContext::~ThreadContext() { +} #endif void ThreadContext::OnDead() { @@ -54,6 +55,8 @@ void ThreadContext::OnCreated(void *arg) { if (tid == 0) return; OnCreatedArgs *args = static_cast(arg); + if (!args->thr) // GCD workers don't have a parent thread. + return; args->thr->fast_state.IncrementEpoch(); // Can't increment epoch w/o writing to the trace as well. TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0); @@ -230,8 +233,10 @@ int ThreadCount(ThreadState *thr) { int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { StatInc(thr, StatThreadCreate); OnCreatedArgs args = { thr, pc }; - int tid = ctx->thread_registry->CreateThread(uid, detached, thr->tid, &args); - DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid); + u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers. + int tid = + ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args); + DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid); StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads()); return tid; } diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index daa5ab2b82..2aa62eb743 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -150,7 +150,7 @@ class Diag { /// An individual diagnostic message argument. struct Arg { - Arg() = default; + Arg() {} Arg(const char *String) : Kind(AK_String), String(String) {} Arg(TypeName TN) : Kind(AK_TypeName), String(TN.getName()) {} Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {} diff --git a/make/config.mk b/make/config.mk index 094fd160f9..0998aca0de 100644 --- a/make/config.mk +++ b/make/config.mk @@ -44,6 +44,6 @@ endif ### # Common compiler options COMMON_INCLUDES=-I${ProjSrcRoot}/lib -I${ProjSrcRoot}/include -COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -fPIC -funwind-tables $(COMMON_INCLUDES) -COMMON_CFLAGS=-fPIC $(COMMON_INCLUDES) +COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -funwind-tables $(COMMON_INCLUDES) +COMMON_CFLAGS=$(COMMON_INCLUDES) COMMON_ASMFLAGS=$(COMMON_INCLUDES) diff --git a/make/platform/clang_darwin.mk b/make/platform/clang_darwin.mk deleted file mode 100644 index dff26943be..0000000000 --- a/make/platform/clang_darwin.mk +++ /dev/null @@ -1,566 +0,0 @@ -# These are the functions which clang needs when it is targeting a previous -# version of the OS. The issue is that the backend may use functions which were -# not present in the libgcc that shipped on the platform. In such cases, we link -# with a version of the library which contains private_extern definitions of all -# the extra functions which might be referenced. - -Description := Static runtime libraries for clang/Darwin. - -# A function that ensures we don't try to build for architectures and SDKs -# that we don't have working toolchains for. Arguments: -# (1): List of architectures -# (2): Library name -# (3): SDK path -# The result is a possibly empty subset of the architectures from argument 1. -CheckArches = \ - $(shell \ - result=""; \ - if [ "X$(3)" != X ]; then \ - for arch in $(1); do \ - if $(LD) -v 2>&1 | grep "configured to support" \ - | tr ' ' '\n' | grep "^$$arch$$" >/dev/null 2>/dev/null; then \ - if $(CC) -arch $$arch \ - -integrated-as \ - $(ProjSrcRoot)/make/platform/clang_darwin_test_input.c \ - -isysroot $(3) \ - -o /dev/null > /dev/null 2> /dev/null; then \ - result="$$result$$arch "; \ - else \ - printf 1>&2 \ - "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'"; \ - printf 1>&2 " (clang or system libraries do not support it)\n"; \ - fi; \ - else \ - printf 1>&2 \ - "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'";\ - printf 1>&2 " (ld does not support it)\n"; \ - fi; \ - done; \ - fi; \ - echo $$result) - -XCRun = \ - $(shell \ - result=`xcrun -find $(1) 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=$(1); fi; \ - echo $$result) -# Prefer building with the internal SDKs. -XCRunSdkPath = \ - $(shell \ - result=`xcrun --sdk $(1).internal --show-sdk-path 2> /dev/null`; \ - if [ "$$?" != "0" ]; then \ - result=`xcrun --sdk $(1) --show-sdk-path 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=""; fi; \ - fi; \ - echo $$result) -### - -CC := $(call XCRun,clang) -LD := $(shell $(CC) -print-prog-name=ld) -AR := $(call XCRun,ar) -RANLIB := $(call XCRun,ranlib) -STRIP := $(call XCRun,strip) -LIPO := $(call XCRun,lipo) -DSYMUTIL := $(call XCRun,dsymutil) - -OSX_SDK := $(call XCRunSdkPath,macosx) -IOS_SDK := $(call XCRunSdkPath,iphoneos) -IOSSIM_SDK := $(call XCRunSdkPath,iphonesimulator) - -Configs := -UniversalArchs := - -# Configuration solely for providing access to an eprintf symbol, which may -# still be referenced from Darwin system headers. This symbol is only ever -# needed on i386. -Configs += eprintf -UniversalArchs.eprintf := $(call CheckArches,i386,eprintf,$(OSX_SDK)) - -# Configuration for targeting 10.4. We need a few functions missing from -# libgcc_s.10.4.dylib. We only build x86 slices since clang doesn't really -# support targeting PowerPC. -Configs += 10.4 -UniversalArchs.10.4 := $(call CheckArches,i386 x86_64,10.4,$(OSX_SDK)) - -# Configuration for targeting iOS for a couple of functions that didn't -# make it into libSystem. -Configs += ios -UniversalArchs.ios := $(call CheckArches,i386 x86_64,ios,$(IOSSIM_SDK)) -UniversalArchs.ios += $(call CheckArches,armv7 arm64,ios,$(IOS_SDK)) - -# Configuration for targeting OSX. These functions may not be in libSystem -# so we should provide our own. -Configs += osx -UniversalArchs.osx := $(call CheckArches,i386 x86_64 x86_64h,osx,$(OSX_SDK)) - -# Configuration for use with kernel/kexts. -Configs += cc_kext -UniversalArchs.cc_kext := $(call CheckArches,i386 x86_64 x86_64h,cc_kext,$(OSX_SDK)) - -# Configuration for use with iOS kernel/kexts -Configs += cc_kext_ios -UniversalArchs.cc_kext_ios += $(call CheckArches,armv7,cc_kext_ios,$(IOS_SDK)) - -# Configurations which define the profiling support functions. -Configs += profile_osx -UniversalArchs.profile_osx := $(call CheckArches,i386 x86_64 x86_64h,profile_osx,$(OSX_SDK)) -Configs += profile_ios -UniversalArchs.profile_ios := $(call CheckArches,i386 x86_64,profile_ios,$(IOSSIM_SDK)) -UniversalArchs.profile_ios += $(call CheckArches,armv7 arm64,profile_ios,$(IOS_SDK)) - -# Configurations which define the ASAN support functions. -Configs += asan_osx_dynamic -UniversalArchs.asan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,asan_osx_dynamic,$(OSX_SDK)) - -Configs += asan_iossim_dynamic -UniversalArchs.asan_iossim_dynamic := $(call CheckArches,i386 x86_64,asan_iossim_dynamic,$(IOSSIM_SDK)) - -Configs += ubsan_osx_dynamic -UniversalArchs.ubsan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx_dynamic,$(OSX_SDK)) - -Configs += ubsan_iossim_dynamic -UniversalArchs.ubsan_iossim_dynamic := $(call CheckArches,i386 x86_64,ubsan_iossim_dynamic,$(IOSSIM_SDK)) - -# Darwin 10.6 has a bug in cctools that makes it unable to use ranlib on our ARM -# object files. If we are on that platform, strip out all ARM archs. We still -# build the libraries themselves so that Clang can find them where it expects -# them, even though they might not have an expected slice. -ifneq ($(shell test -x /usr/bin/sw_vers && sw_vers -productVersion | grep 10.6),) -UniversalArchs.ios := $(filter-out armv7, $(UniversalArchs.ios)) -UniversalArchs.cc_kext_ios := $(filter-out armv7, $(UniversalArchs.cc_kext_ios)) -UniversalArchs.profile_ios := $(filter-out armv7, $(UniversalArchs.profile_ios)) -endif - -# If RC_SUPPORTED_ARCHS is defined, treat it as a list of the architectures we -# are intended to support and limit what we try to build to that. -ifneq ($(RC_SUPPORTED_ARCHS),) -$(foreach config,$(Configs),\ - $(call Set,UniversalArchs.$(config),\ - $(filter $(RC_SUPPORTED_ARCHS),$(UniversalArchs.$(config))))) -endif - -# Remove empty configs if we end up dropping all the requested -# archs for a particular config. -$(foreach config,$(Configs),\ - $(if $(strip $(UniversalArchs.$(config))),,\ - $(call Set,Configs,$(filter-out $(config),$(Configs))))) - -### - -# Forcibly strip off any -arch, as that totally breaks our universal support. -override CC := $(subst -arch ,-arch_,$(CC)) -override CC := $(patsubst -arch_%,,$(CC)) - -CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer - -# Always set deployment target arguments for every build, these libraries should -# never depend on the environmental overrides. We simply set them to minimum -# supported deployment target -- nothing in the compiler-rt libraries should -# actually depend on the deployment target. -OSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.4 -IOS_DEPLOYMENT_ARGS := -mios-version-min=1.0 -IOS6_DEPLOYMENT_ARGS := -mios-version-min=6.0 -IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=1.0 - -OSX_DEPLOYMENT_ARGS += -isysroot $(OSX_SDK) -IOS_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) -IOS6_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) -IOSSIM_DEPLOYMENT_ARGS += -isysroot $(IOSSIM_SDK) - -CFLAGS.eprintf := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.10.4 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) - -SANITIZER_MACOSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.7 -SANITIZER_IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=7.0 \ - -isysroot $(IOSSIM_SDK) -SANITIZER_CFLAGS := -fno-builtin -gline-tables-only -stdlib=libc++ - -CFLAGS.asan_osx_dynamic := \ - $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) \ - -DMAC_INTERPOSE_FUNCTIONS=1 \ - -DASAN_DYNAMIC=1 - -CFLAGS.asan_iossim_dynamic := \ - $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) \ - -DMAC_INTERPOSE_FUNCTIONS=1 \ - -DASAN_DYNAMIC=1 - -CFLAGS.ubsan_osx_dynamic := \ - $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) - -CFLAGS.ubsan_iossim_dynamic := \ - $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) - - -CFLAGS.ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7k := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7s := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) - -SANITIZER_LDFLAGS := -stdlib=libc++ -lc++ -lc++abi - -SHARED_LIBRARY.asan_osx_dynamic := 1 -LDFLAGS.asan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \ - $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.asan_iossim_dynamic := 1 -LDFLAGS.asan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_iossim_dynamic.dylib \ - -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.ubsan_osx_dynamic := 1 -LDFLAGS.ubsan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_osx_dynamic.dylib \ - $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.ubsan_iossim_dynamic := 1 -LDFLAGS.ubsan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_iossim_dynamic.dylib \ - -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) - -ifneq ($(OSX_SDK),) -CFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK) -LDFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK) -CFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK) -LDFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK) -endif - -ATOMIC_FUNCTIONS := \ - atomic_flag_clear \ - atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence \ - atomic_thread_fence - -FP16_FUNCTIONS := \ - extendhfsf2 \ - truncdfhf2 \ - truncsfhf2 - -FUNCTIONS.eprintf := eprintf -FUNCTIONS.10.4 := eprintf floatundidf floatundisf floatundixf - -FUNCTIONS.ios := divmodsi4 udivmodsi4 mulosi4 mulodi4 muloti4 \ - $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) -# On x86, the divmod functions reference divsi. -FUNCTIONS.ios.i386 := $(FUNCTIONS.ios) \ - divsi3 udivsi3 -FUNCTIONS.ios.x86_64 := $(FUNCTIONS.ios.i386) -FUNCTIONS.ios.arm64 := mulsc3 muldc3 divsc3 divdc3 udivti3 umodti3 \ - $(ATOMIC_FUNCTIONS) - -FUNCTIONS.osx := mulosi4 mulodi4 muloti4 $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) - -FUNCTIONS.profile_osx := GCDAProfiling InstrProfiling InstrProfilingBuffer \ - InstrProfilingFile InstrProfilingPlatformDarwin \ - InstrProfilingRuntime InstrProfilingUtil -FUNCTIONS.profile_ios := $(FUNCTIONS.profile_osx) - -FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ - $(InterceptionFunctions) \ - $(SanitizerCommonFunctions) \ - $(AsanDynamicFunctions) \ - $(UbsanFunctions) $(UbsanCXXFunctions) - -FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ - $(InterceptionFunctions) \ - $(SanitizerCommonFunctions) \ - $(AsanDynamicFunctions) \ - $(UbsanFunctions) $(UbsanCXXFunctions) - -FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ - $(SanitizerCommonFunctions) \ - $(UbsanStandaloneFunctions) - -FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ - $(SanitizerCommonFunctions) \ - $(UbsanStandaloneFunctions) - -CCKEXT_PROFILE_FUNCTIONS := \ - InstrProfiling \ - InstrProfilingBuffer \ - InstrProfilingPlatformDarwin - -CCKEXT_COMMON_FUNCTIONS := \ - $(CCKEXT_PROFILE_FUNCTIONS) \ - absvdi2 \ - absvsi2 \ - addvdi3 \ - addvsi3 \ - ashldi3 \ - ashrdi3 \ - bswapdi2 \ - bswapsi2 \ - clzdi2 \ - clzsi2 \ - cmpdi2 \ - ctzdi2 \ - ctzsi2 \ - divdc3 \ - divdi3 \ - divsc3 \ - divmodsi4 \ - udivmodsi4 \ - do_global_dtors \ - eprintf \ - extendhfsf2 \ - ffsdi2 \ - fixdfdi \ - fixsfdi \ - fixunsdfdi \ - fixunsdfsi \ - fixunssfdi \ - fixunssfsi \ - floatdidf \ - floatdisf \ - floatundidf \ - floatundisf \ - gcc_bcmp \ - lshrdi3 \ - moddi3 \ - muldc3 \ - muldi3 \ - mulsc3 \ - mulvdi3 \ - mulvsi3 \ - negdi2 \ - negvdi2 \ - negvsi2 \ - paritydi2 \ - paritysi2 \ - popcountdi2 \ - popcountsi2 \ - powidf2 \ - powisf2 \ - subvdi3 \ - subvsi3 \ - truncdfhf2 \ - truncsfhf2 \ - ucmpdi2 \ - udiv_w_sdiv \ - udivdi3 \ - udivmoddi4 \ - umoddi3 - -CCKEXT_ARM_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ - adddf3 \ - addsf3 \ - aeabi_cdcmpeq \ - aeabi_cdrcmple \ - aeabi_cfcmpeq \ - aeabi_cfrcmple \ - aeabi_dcmpeq \ - aeabi_dcmpge \ - aeabi_dcmpgt \ - aeabi_dcmple \ - aeabi_dcmplt \ - aeabi_drsub \ - aeabi_fcmpeq \ - aeabi_fcmpge \ - aeabi_fcmpgt \ - aeabi_fcmple \ - aeabi_fcmplt \ - aeabi_frsub \ - aeabi_idivmod \ - aeabi_uidivmod \ - cmpdf2 \ - cmpsf2 \ - div0 \ - divdf3 \ - divsf3 \ - divsi3 \ - extendsfdf2 \ - ffssi2 \ - fixdfsi \ - fixsfsi \ - floatsidf \ - floatsisf \ - floatunsidf \ - floatunsisf \ - comparedf2 \ - comparesf2 \ - modsi3 \ - muldf3 \ - mulsf3 \ - mulodi4 \ - negdf2 \ - negsf2 \ - subdf3 \ - subsf3 \ - switch16 \ - switch32 \ - switch8 \ - switchu8 \ - truncdfsf2 \ - udivsi3 \ - umodsi3 \ - unorddf2 \ - unordsf2 - -CCKEXT_ARMVFP_FUNCTIONS := $(CCKEXT_ARM_FUNCTIONS) \ - adddf3vfp \ - addsf3vfp \ - divdf3vfp \ - divsf3vfp \ - eqdf2vfp \ - eqsf2vfp \ - extendsfdf2vfp \ - fixdfsivfp \ - fixsfsivfp \ - fixunsdfsivfp \ - fixunssfsivfp \ - floatsidfvfp \ - floatsisfvfp \ - floatunssidfvfp \ - floatunssisfvfp \ - gedf2vfp \ - gesf2vfp \ - gtdf2vfp \ - gtsf2vfp \ - ledf2vfp \ - lesf2vfp \ - ltdf2vfp \ - ltsf2vfp \ - muldf3vfp \ - mulsf3vfp \ - nedf2vfp \ - nesf2vfp \ - subdf3vfp \ - subsf3vfp \ - truncdfsf2vfp \ - unorddf2vfp \ - unordsf2vfp - -CCKEXT_ARM64_FUNCTIONS := \ - $(CCKEXT_PROFILE_FUNCTIONS) \ - divdc3 \ - divsc3 \ - muldc3 \ - mulsc3 \ - udivti3 \ - umodti3 - -FUNCTIONS.cc_kext_ios.armv7 := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.armv7k := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.armv7s := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.arm64 := $(CCKEXT_ARM64_FUNCTIONS) - -CCKEXT_X86_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ - divxc3 \ - fixunsxfdi \ - fixunsxfsi \ - fixxfdi \ - floatdixf \ - floatundixf \ - mulxc3 \ - powixf2 - -FUNCTIONS.cc_kext.i386 := $(CCKEXT_X86_FUNCTIONS) \ - ffssi2 \ - i686.get_pc_thunk.eax \ - i686.get_pc_thunk.ebp \ - i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx \ - i686.get_pc_thunk.edi \ - i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi - -FUNCTIONS.cc_kext.x86_64 := $(CCKEXT_X86_FUNCTIONS) \ - absvti2 \ - addvti3 \ - ashlti3 \ - ashrti3 \ - clzti2 \ - cmpti2 \ - ctzti2 \ - divti3 \ - ffsti2 \ - fixdfti \ - fixsfti \ - fixunsdfti \ - fixunssfti \ - fixunsxfti \ - fixxfti \ - floattidf \ - floattisf \ - floattixf \ - floatuntidf \ - floatuntisf \ - floatuntixf \ - lshrti3 \ - modti3 \ - multi3 \ - mulvti3 \ - negti2 \ - negvti2 \ - parityti2 \ - popcountti2 \ - subvti3 \ - ucmpti2 \ - udivmodti4 \ - udivti3 \ - umodti3 - -FUNCTIONS.cc_kext.x86_64h := $(FUNCTIONS.cc_kext.x86_64) - -# FIXME: Currently, compiler-rt is missing implementations for a number of the -# functions that need to go into libcc_kext.a. Filter them out for now. -CCKEXT_MISSING_FUNCTIONS := \ - cmpdf2 cmpsf2 div0 \ - ffssi2 \ - udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ - bswapsi2 \ - gcc_bcmp \ - do_global_dtors \ - i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi \ - aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ - aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub aeabi_fcmpeq \ - aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt aeabi_frsub aeabi_idivmod \ - aeabi_uidivmod - -FUNCTIONS.cc_kext_ios.armv7 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7)) -FUNCTIONS.cc_kext_ios.armv7k := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7k)) -FUNCTIONS.cc_kext_ios.armv7s := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7s)) -FUNCTIONS.cc_kext_ios.arm64 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.arm64)) -FUNCTIONS.cc_kext.i386 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.i386)) -FUNCTIONS.cc_kext.x86_64 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64)) -FUNCTIONS.cc_kext.x86_64h := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64h)) - -KERNEL_USE.cc_kext := 1 -KERNEL_USE.cc_kext_ios := 1 - -VISIBILITY_HIDDEN := 1 - -SHARED_LIBRARY_SUFFIX := dylib diff --git a/make/platform/clang_darwin_test_input.c b/make/platform/clang_darwin_test_input.c deleted file mode 100644 index b406a28a63..0000000000 --- a/make/platform/clang_darwin_test_input.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Include the headers we use in int_lib.h, to verify that they work. */ - -#include -#include -#include -#include -#include - -// Force us to link at least one symbol in a system library -// to detect systems where we don't have those for a given -// architecture. -int main(int argc, const char **argv) { - int x; - memcpy(&x,&argc,sizeof(int)); -} diff --git a/make/platform/clang_linux.mk b/make/platform/clang_linux.mk deleted file mode 100644 index 7b109d56c0..0000000000 --- a/make/platform/clang_linux.mk +++ /dev/null @@ -1,90 +0,0 @@ -Description := Static runtime libraries for clang/Linux. - -### - -CC := clang -Arch := unknown -Configs := - -# We don't currently have any general purpose way to target architectures other -# than the compiler defaults (because there is no generalized way to invoke -# cross compilers). For now, we just find the target architecture of the -# compiler and only define configurations we know that compiler can generate. -CompilerTargetTriple := $(shell \ - LANG=C $(CC) -v 2>&1 | grep 'Target:' | cut -d' ' -f2) -ifeq ($(CompilerTargetTriple),) -$(error "unable to infer compiler target triple for $(CC)") -endif - -# Only define configs if we detected a linux target. -ifneq ($(findstring -linux-,$(CompilerTargetTriple)),) - -# Define configs only if arch in triple is i386 or x86_64 -CompilerTargetArch := $(firstword $(subst -, ,$(CompilerTargetTriple))) -ifeq ($(call contains,i386 x86_64,$(CompilerTargetArch)),true) - -# TryCompile compiler source flags -# Returns exit code of running a compiler invocation. -TryCompile = \ - $(shell \ - cflags=""; \ - for flag in $(3); do \ - cflags="$$cflags $$flag"; \ - done; \ - $(1) $$cflags $(2) -o /dev/null > /dev/null 2> /dev/null ; \ - echo $$?) - -test_source = $(ProjSrcRoot)/make/platform/clang_linux_test_input.c -ifeq ($(CompilerTargetArch),i386) - SupportedArches := i386 - ifeq ($(call TryCompile,$(CC),$(test_source),-m64),0) - SupportedArches += x86_64 - endif -else - SupportedArches := x86_64 - ifeq ($(call TryCompile,$(CC),$(test_source),-m32),0) - SupportedArches += i386 - endif -endif - -# Build runtime libraries for i386. -ifeq ($(call contains,$(SupportedArches),i386),true) -Configs += builtins-i386 profile-i386 -Arch.builtins-i386 := i386 -Arch.profile-i386 := i386 -endif - -# Build runtime libraries for x86_64. -ifeq ($(call contains,$(SupportedArches),x86_64),true) -Configs += builtins-x86_64 profile-x86_64 -Arch.builtins-x86_64 := x86_64 -Arch.profile-x86_64 := x86_64 -endif - -endif - -endif - -### - -CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer - -CFLAGS.builtins-i386 := $(CFLAGS) -m32 -CFLAGS.builtins-x86_64 := $(CFLAGS) -m64 -CFLAGS.profile-i386 := $(CFLAGS) -m32 -CFLAGS.profile-x86_64 := $(CFLAGS) -m64 - -FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386) -FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64) -FUNCTIONS.profile-i386 := GCDAProfiling InstrProfiling InstrProfilingBuffer \ - InstrProfilingFile InstrProfilingPlatformOther \ - InstrProfilingRuntime InstrProfilingUtil -FUNCTIONS.profile-x86_64 := $(FUNCTIONS.profile-i386) - -# Always use optimized variants. -OPTIMIZED := 1 - -# We don't need to use visibility hidden on Linux. -VISIBILITY_HIDDEN := 0 - -SHARED_LIBRARY_SUFFIX := so diff --git a/make/platform/clang_linux_test_input.c b/make/platform/clang_linux_test_input.c deleted file mode 100644 index e65ce9860a..0000000000 --- a/make/platform/clang_linux_test_input.c +++ /dev/null @@ -1,4 +0,0 @@ -// This file is used to check if we can produce working executables -// for i386 and x86_64 archs on Linux. -#include -int main(){} diff --git a/make/platform/clang_macho_embedded.mk b/make/platform/clang_macho_embedded.mk deleted file mode 100644 index d7870d491f..0000000000 --- a/make/platform/clang_macho_embedded.mk +++ /dev/null @@ -1,297 +0,0 @@ -# These are the functions which clang needs when it is targeting a previous -# version of the OS. The issue is that the backend may use functions which were -# not present in the libgcc that shipped on the platform. In such cases, we link -# with a version of the library which contains private_extern definitions of all -# the extra functions which might be referenced. - -Description := Static runtime libraries for embedded clang/Darwin - -# A function that ensures we don't try to build for architectures that we -# don't have working toolchains for. -CheckArches = \ - $(shell \ - result=""; \ - for arch in $(1); do \ - if $(CC) -arch $$arch -c \ - -integrated-as \ - $(ProjSrcRoot)/make/platform/clang_macho_embedded_test_input.c \ - -o /dev/null > /dev/null 2> /dev/null; then \ - result="$$result$$arch "; \ - else \ - printf 1>&2 \ - "warning: clang_macho_embedded.mk: dropping arch '$$arch' from lib '$(2)'\n"; \ - fi; \ - done; \ - echo $$result) - -XCRun = \ - $(shell \ - result=`xcrun -find $(1) 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=$(1); fi; \ - echo $$result) - -### - -CC := $(call XCRun,clang) -AR := $(call XCRun,ar) -RANLIB := $(call XCRun,ranlib) -STRIP := $(call XCRun,strip) -LIPO := $(call XCRun,lipo) -DSYMUTIL := $(call XCRun,dsymutil) - -Configs := -UniversalArchs := - -# Soft-float version of the runtime. No floating-point instructions will be used -# and the ABI (out of necessity) passes floating values in normal registers: -# non-VFP variant of the AAPCS. -UniversalArchs.soft_static := $(call CheckArches,armv6m armv7m armv7em armv7,soft_static) -Configs += $(if $(UniversalArchs.soft_static),soft_static) - -# Hard-float version of the runtime. On ARM VFP instructions and registers are -# allowed, and floating point values get passed in them. VFP variant of the -# AAPCS. -UniversalArchs.hard_static := $(call CheckArches,armv7em armv7 i386 x86_64,hard_static) -Configs += $(if $(UniversalArchs.hard_static),hard_static) - -UniversalArchs.soft_pic := $(call CheckArches,armv6m armv7m armv7em armv7,soft_pic) -Configs += $(if $(UniversalArchs.soft_pic),soft_pic) - -UniversalArchs.hard_pic := $(call CheckArches,armv7em armv7 i386 x86_64,hard_pic) -Configs += $(if $(UniversalArchs.hard_pic),hard_pic) - -CFLAGS := -Wall -Werror -Oz -fomit-frame-pointer -ffreestanding - -PIC_CFLAGS := -fPIC -STATIC_CFLAGS := -static - -CFLAGS_SOFT := -mfloat-abi=soft -CFLAGS_HARD := -mfloat-abi=hard - -CFLAGS_ARMV7 := -target thumbv7-apple-darwin-eabi -CFLAGS_I386 := -march=pentium - -CFLAGS.soft_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_SOFT) -CFLAGS.hard_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_HARD) -CFLAGS.soft_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_SOFT) -CFLAGS.hard_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_HARD) - -CFLAGS.soft_static.armv7 := $(CFLAGS.soft_static) $(CFLAGS_ARMV7) -CFLAGS.hard_static.armv7 := $(CFLAGS.hard_static) $(CFLAGS_ARMV7) -CFLAGS.soft_pic.armv7 := $(CFLAGS.soft_pic) $(CFLAGS_ARMV7) -CFLAGS.hard_pic.armv7 := $(CFLAGS.hard_pic) $(CFLAGS_ARMV7) - -# x86 platforms ignore -mfloat-abi options and complain about doing so. Despite -# this they're hard-float. -CFLAGS.hard_static.i386 := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_I386) -CFLAGS.hard_pic.i386 := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_I386) -CFLAGS.hard_static.x86_64 := $(CFLAGS) $(STATIC_CFLAGS) -CFLAGS.hard_pic.x86_64 := $(CFLAGS) $(PIC_CFLAGS) - -# Functions not wanted: -# + eprintf is obsolete anyway -# + *vfp: designed for Thumb1 CPUs with VFPv2 - -COMMON_FUNCTIONS := \ - absvdi2 \ - absvsi2 \ - addvdi3 \ - addvsi3 \ - ashldi3 \ - ashrdi3 \ - bswapdi2 \ - bswapsi2 \ - clzdi2 \ - clzsi2 \ - cmpdi2 \ - ctzdi2 \ - ctzsi2 \ - divdc3 \ - divdi3 \ - divsc3 \ - divmodsi4 \ - udivmodsi4 \ - do_global_dtors \ - ffsdi2 \ - fixdfdi \ - fixsfdi \ - fixunsdfdi \ - fixunsdfsi \ - fixunssfdi \ - fixunssfsi \ - floatdidf \ - floatdisf \ - floatundidf \ - floatundisf \ - gcc_bcmp \ - lshrdi3 \ - moddi3 \ - muldc3 \ - muldi3 \ - mulsc3 \ - mulvdi3 \ - mulvsi3 \ - negdi2 \ - negvdi2 \ - negvsi2 \ - paritydi2 \ - paritysi2 \ - popcountdi2 \ - popcountsi2 \ - powidf2 \ - powisf2 \ - subvdi3 \ - subvsi3 \ - ucmpdi2 \ - udiv_w_sdiv \ - udivdi3 \ - udivmoddi4 \ - umoddi3 \ - adddf3 \ - addsf3 \ - cmpdf2 \ - cmpsf2 \ - div0 \ - divdf3 \ - divsf3 \ - divsi3 \ - extendsfdf2 \ - extendhfsf2 \ - ffssi2 \ - fixdfsi \ - fixsfsi \ - floatsidf \ - floatsisf \ - floatunsidf \ - floatunsisf \ - comparedf2 \ - comparesf2 \ - modsi3 \ - muldf3 \ - mulsf3 \ - negdf2 \ - negsf2 \ - subdf3 \ - subsf3 \ - truncdfhf2 \ - truncdfsf2 \ - truncsfhf2 \ - udivsi3 \ - umodsi3 \ - unorddf2 \ - unordsf2 \ - atomic_flag_clear \ - atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence \ - atomic_thread_fence - -ARM_FUNCTIONS := \ - aeabi_cdcmpeq \ - aeabi_cdrcmple \ - aeabi_cfcmpeq \ - aeabi_cfrcmple \ - aeabi_dcmpeq \ - aeabi_dcmpge \ - aeabi_dcmpgt \ - aeabi_dcmple \ - aeabi_dcmplt \ - aeabi_drsub \ - aeabi_fcmpeq \ - aeabi_fcmpge \ - aeabi_fcmpgt \ - aeabi_fcmple \ - aeabi_fcmplt \ - aeabi_frsub \ - aeabi_idivmod \ - aeabi_uidivmod \ - -# ARM Assembly implementation which requires Thumb2 (i.e. won't work on v6M). -THUMB2_FUNCTIONS := \ - switch16 \ - switch32 \ - switch8 \ - switchu8 \ - sync_fetch_and_add_4 \ - sync_fetch_and_sub_4 \ - sync_fetch_and_and_4 \ - sync_fetch_and_or_4 \ - sync_fetch_and_xor_4 \ - sync_fetch_and_nand_4 \ - sync_fetch_and_max_4 \ - sync_fetch_and_umax_4 \ - sync_fetch_and_min_4 \ - sync_fetch_and_umin_4 \ - sync_fetch_and_add_8 \ - sync_fetch_and_sub_8 \ - sync_fetch_and_and_8 \ - sync_fetch_and_or_8 \ - sync_fetch_and_xor_8 \ - sync_fetch_and_nand_8 \ - sync_fetch_and_max_8 \ - sync_fetch_and_umax_8 \ - sync_fetch_and_min_8 \ - sync_fetch_and_umin_8 - -I386_FUNCTIONS := \ - i686.get_pc_thunk.eax \ - i686.get_pc_thunk.ebp \ - i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx \ - i686.get_pc_thunk.edi \ - i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi - -# FIXME: Currently, compiler-rt is missing implementations for a number of the -# functions. Filter them out for now. -MISSING_FUNCTIONS := \ - cmpdf2 cmpsf2 div0 \ - ffssi2 \ - udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ - bswapsi2 \ - gcc_bcmp \ - do_global_dtors \ - i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi \ - aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ - aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub \ - aeabi_fcmpeq \ aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt \ - aeabi_frsub aeabi_idivmod aeabi_uidivmod - -FUNCTIONS_ARMV6M := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) -FUNCTIONS_ARM_ALL := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) $(THUMB2_FUNCTIONS) -FUNCTIONS_I386 := $(COMMON_FUNCTIONS) $(I386_FUNCTIONS) -FUNCTIONS_X86_64 := $(COMMON_FUNCTIONS) - -FUNCTIONS_ARMV6M := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARMV6M)) -FUNCTIONS_ARM_ALL := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARM_ALL)) -FUNCTIONS_I386 := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_I386)) -FUNCTIONS_X86_64 := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_X86_64)) - -FUNCTIONS.soft_static.armv6m := $(FUNCTIONS_ARMV6M) -FUNCTIONS.soft_pic.armv6m := $(FUNCTIONS_ARMV6M) - -FUNCTIONS.soft_static.armv7m := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7m := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.soft_static.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_static.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_pic.armv7em := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.soft_static.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_static.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_pic.armv7 := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.hard_static.i386 := $(FUNCTIONS_I386) -FUNCTIONS.hard_pic.i386 := $(FUNCTIONS_I386) - -FUNCTIONS.hard_static.x86_64 := $(FUNCTIONS_X86_64) -FUNCTIONS.hard_pic.x86_64 := $(FUNCTIONS_X86_64) diff --git a/make/platform/clang_macho_embedded_test_input.c b/make/platform/clang_macho_embedded_test_input.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/make/platform/darwin_bni.mk b/make/platform/darwin_bni.mk deleted file mode 100644 index 8e066e8e31..0000000000 --- a/make/platform/darwin_bni.mk +++ /dev/null @@ -1,135 +0,0 @@ - -Description := Target for Darwin using an Apple-style build. - -Configs := Debug Release Profile Static - -# We override this with RC_ARCHS because B&I may want to build on an ARCH we -# haven't explicitly defined support for. If all goes well, this will just work -# and the resulting lib will just have generic versions for anything unknown. -UniversalArchs := $(RC_ARCHS) - -ifneq (,$(SDKROOT)) - override CC := $(shell xcrun -sdk $(SDKROOT) -find clang || echo "false") - AR := $(shell xcrun -sdk $(SDKROOT) -find ar || echo "false") - RANLIB := $(shell xcrun -sdk $(SDKROOT) -find ranlib || echo "false") - STRIP := $(shell xcrun -sdk $(SDKROOT) -find strip || echo "false") - LIPO := $(shell xcrun -sdk $(SDKROOT) -find lipo || echo "false") - DSYMUTIL := $(shell xcrun -sdk $(SDKROOT) -find dsymutil || echo "false") -endif - -ifneq ($(IPHONEOS_DEPLOYMENT_TARGET),) - DEPLOYMENT_FLAGS := -miphoneos-version-min=$(IPHONEOS_DEPLOYMENT_TARGET) -else - ifneq ($(MACOSX_DEPLOYMENT_TARGET),) - DEPLOYMENT_FLAGS := -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) - endif -endif - -ifneq (,$(SDKROOT)) - DEPLOYMENT_FLAGS += -isysroot $(SDKROOT) -endif - -CFLAGS := -Wall -Os -fomit-frame-pointer -g $(DEPLOYMENT_FLAGS) -CFLAGS.Static := $(CFLAGS) -static -DYLIB_FLAGS := $(DEPLOYMENT_FLAGS) \ - -Xarch_arm -Wl,-alias_list,$(SRCROOT)/lib/builtins/arm/softfloat-alias.list - -VISIBILITY_HIDDEN := 0 -VISIBILITY_HIDDEN.Static := 1 - - -FUNCTIONS := absvdi2 absvsi2 addvdi3 addvsi3 ashldi3 ashrdi3 \ - clzdi2 clzsi2 cmpdi2 ctzdi2 ctzsi2 \ - divdc3 divdi3 divsc3 ffsdi2 \ - fixdfdi fixsfdi fixunsdfdi fixunsdfsi fixunssfdi \ - fixunssfsi floatdidf floatdisf floatundidf floatundisf \ - gcc_personality_v0 lshrdi3 moddi3 muldc3 muldi3 mulosi4 \ - mulodi4 muloti4 mulsc3 mulvdi3 mulvsi3 negdi2 negvdi2 negvsi2 \ - paritydi2 paritysi2 popcountdi2 popcountsi2 powidf2 \ - powisf2 subvdi3 subvsi3 ucmpdi2 udivdi3 \ - udivmoddi4 umoddi3 apple_versioning eprintf atomic \ - atomic_flag_clear atomic_flag_clear_explicit \ - atomic_flag_test_and_set atomic_flag_test_and_set_explicit \ - atomic_signal_fence atomic_thread_fence \ - extendhfsf2 truncdfhf2 truncsfhf2 - -FUNCTIONS.i386 := $(FUNCTIONS) \ - divxc3 fixunsxfdi fixunsxfsi fixxfdi floatdixf \ - floatundixf mulxc3 powixf2 clear_cache \ - enable_execute_stack -FUNCTIONS.ppc := $(FUNCTIONS) \ - divtc3 fixtfdi fixunstfdi floatditf floatunditf \ - gcc_qadd gcc_qdiv gcc_qmul gcc_qsub multc3 \ - powitf2 restFP saveFP trampoline_setup \ - clear_cache enable_execute_stack -FUNCTIONS.x86_64 := $(FUNCTIONS) \ - absvti2 addvti3 ashlti3 ashrti3 clzti2 cmpti2 \ - ctzti2 divti3 divxc3 ffsti2 fixdfti fixsfti \ - fixunsdfti fixunssfti fixunsxfdi fixunsxfsi \ - fixunsxfti fixxfdi fixxfti floatdixf floattidf \ - floattisf floattixf floatundixf floatuntidf \ - floatuntisf floatuntixf lshrti3 modti3 multi3 \ - muloti4 mulvti3 mulxc3 negti2 negvti2 parityti2 \ - popcountti2 powixf2 subvti3 ucmpti2 udivmodti4 \ - udivti3 umodti3 clear_cache enable_execute_stack - -FUNCTIONS.armv4t := $(FUNCTIONS) - -FUNCTIONS.armv5 := $(FUNCTIONS) \ - adddf3 addsf3 bswapdi2 bswapsi2 \ - comparedf2 comparesf2 extendsfdf2 \ - divdf3 divsf3 \ - fixdfsi fixsfsi fixunsdfsi fixunssfsi \ - floatsidf floatsisf floatunsidf floatunsisf \ - muldf3 mulsf3 \ - negdf2 negsf2 \ - truncdfsf2 \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ - switch8 switchu8 switch16 switch32 \ - sync_synchronize - -FUNCTIONS.armv6 := $(FUNCTIONS) \ - comparedf2 comparesf2 \ - adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ - divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ - fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ - floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ - gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ - ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ - muldf3vfp mulsf3vfp \ - nedf2vfp nesf2vfp \ - subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ - switch8 switchu8 switch16 switch32 \ - restore_vfp_d8_d15_regs save_vfp_d8_d15_regs \ - sync_synchronize - -FUNCTIONS.armv7 := $(FUNCTIONS) \ - comparedf2 comparesf2 \ - adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ - divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ - fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ - floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ - gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ - ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ - muldf3vfp mulsf3vfp \ - nedf2vfp nesf2vfp \ - subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 - -FUNCTIONS.armv7s := $(FUNCTIONS.armv7) - -FUNCTIONS.arm64 := divti3 modti3 \ - udivmodti4 \ - udivti3 umodti3 \ - mulsc3 muldc3 \ - powisf2 powidf2 \ - clzti2 \ - fixdfti fixsfti \ - fixunsdfti fixunssfti fixunssfti \ - floattidf floattisf floatuntidf floatuntisf \ - gcc_personality_v0 atomic \ - atomic_flag_clear atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence atomic_thread_fence diff --git a/make/platform/multi_arch.mk b/make/platform/multi_arch.mk deleted file mode 100644 index fe6ac4be0e..0000000000 --- a/make/platform/multi_arch.mk +++ /dev/null @@ -1,15 +0,0 @@ -Description := Example configuration for build two libraries for separate \ -architectures. - -Configs := m32 m64 -Arch := i386 -Arch.m64 := x86_64 - -CC := clang - -CFLAGS := -Wall -Werror -CFLAGS.m32 := $(CFLAGS) -m32 -O3 -CFLAGS.m64 := $(CFLAGS) -m64 -O3 - -FUNCTIONS := moddi3 floatundixf udivdi3 -FUNCTIONS.m64 := $(FUNCTIONS) lshrdi3 diff --git a/make/platform/triple.mk b/make/platform/triple.mk new file mode 100644 index 0000000000..0d68b2eafd --- /dev/null +++ b/make/platform/triple.mk @@ -0,0 +1,78 @@ +# This "platform" file is intended for building compiler-rt using gcc. +# The actual target platform is selected by setting the TargetTriple variable to the corresponding LLVM triple. + +Description := Static runtime libraries for platforms selected by 'TargetTriple' + +# Provide defaults for the required vars +ifndef CC + CC := gcc +endif +ifndef CFLAGS + CFLAGS := -Wall -O3 +endif + +Configs := builtins + +Arch := $(word 1,$(subst -, ,$(TargetTriple))) +ifeq ($(Arch),i686) + Arch := i386 +else ifeq ($(Arch),arm) +ifneq (,$(findstring ios,$(TargetTriple))) + Arch := armv7 +else ifneq (,$(findstring android,$(TargetTriple))) + Arch := armv7 +endif +endif + +# Filter out stuff that gcc cannot compile (these are only needed for clang-generated code anywasys). +CommonFunctions_gcc := $(filter-out atomic% enable_execute_stack,$(CommonFunctions)) + +# Filter out stuff which is not available on specific target +# For example, sync_fetch_and_add_4 uses Thumb instructions, which are unavailable +# when building for arm-linux-androideabi +ifeq ($(TargetTriple),arm-linux-androideabi) + ArchDisabledFunctions := \ + sync_fetch_and_add_4 \ + sync_fetch_and_sub_4 \ + sync_fetch_and_and_4 \ + sync_fetch_and_or_4 \ + sync_fetch_and_xor_4 \ + sync_fetch_and_nand_4 \ + sync_fetch_and_max_4 \ + sync_fetch_and_umax_4 \ + sync_fetch_and_min_4 \ + sync_fetch_and_umin_4 \ + sync_fetch_and_add_8 \ + sync_fetch_and_sub_8 \ + sync_fetch_and_and_8 \ + sync_fetch_and_or_8 \ + sync_fetch_and_xor_8 \ + sync_fetch_and_nand_8 \ + sync_fetch_and_max_8 \ + sync_fetch_and_umax_8 \ + sync_fetch_and_min_8 \ + sync_fetch_and_umin_8 +endif + +# Disable emutls on MIPS +# Rust uses GCC 4.4 to cross-compile, which doesn't have some builtins +ifneq (,$(findstring mips,$(TargetTriple))) + CommonDisabledFunctions := emutls +endif + +# Disable emutls on Windows +# emutls works on POSIX only as it uses pthreads +ifneq (,$(findstring windows,$(TargetTriple))) + CommonDisabledFunctions := emutls +endif + +# Clear cache is builtin on aarch64-apple-ios +# arm64 and aarch64 are synonims, but iOS targets usually use arm64 (history reasons) +ifeq (aarch64-apple-ios,$(subst arm64,aarch64,$(TargetTriple))) +CommonDisabledFunctions := clear_cache +endif + +ArchEnabledFunctions := $(filter-out $(ArchDisabledFunctions),$(value ArchFunctions.$(Arch))) +CommonEnabledFunctions := $(filter-out $(CommonDisabledFunctions),$(CommonFunctions_gcc)) + +FUNCTIONS.builtins := $(CommonEnabledFunctions) $(ArchEnabledFunctions) diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.c index f37072a3ac..9bd32869c9 100644 --- a/test/asan/TestCases/Darwin/interface_symbols_darwin.c +++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.c @@ -43,14 +43,6 @@ // RUN: echo __asan_report_exp_store_n >> %t.interface // RUN: echo __asan_get_current_fake_stack >> %t.interface // RUN: echo __asan_addr_is_in_fake_stack >> %t.interface -// RUN: echo __asan_mz_calloc >> %t.interface -// RUN: echo __asan_mz_destroy >> %t.interface -// RUN: echo __asan_mz_free >> %t.interface -// RUN: echo __asan_mz_malloc >> %t.interface -// RUN: echo __asan_mz_memalign >> %t.interface -// RUN: echo __asan_mz_realloc >> %t.interface -// RUN: echo __asan_mz_size >> %t.interface -// RUN: echo __asan_mz_valloc >> %t.interface // RUN: for i in `jot - 0 10`; do echo __asan_stack_malloc_$i >> %t.interface; done // RUN: for i in `jot - 0 10`; do echo __asan_stack_free_$i >> %t.interface; done diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc index 6840ebe28b..d87d90be47 100644 --- a/test/asan/TestCases/Linux/ptrace.cc +++ b/test/asan/TestCases/Linux/ptrace.cc @@ -1,9 +1,9 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android +// XFAIL: mips // // RUN: %clangxx_asan -O0 %s -o %t && %run %t // RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s -// REQUIRES: x86_64-supported-target,i386-supported-target #include #include @@ -12,6 +12,55 @@ #include #include #include +#include // for iovec +#include // for NT_PRSTATUS +#ifdef __aarch64__ +# include +#endif + +#if defined(__i386__) || defined(__x86_64__) +typedef user_regs_struct regs_struct; +typedef user_fpregs_struct fpregs_struct; +#if defined(__i386__) +#define REG_IP eip +#else +#define REG_IP rip +#endif +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.REG_IP)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (unsigned long) (__fpregs.cwd)) +#define __PTRACE_FPREQUEST PTRACE_GETFPREGS + +#elif defined(__aarch64__) +typedef struct user_pt_regs regs_struct; +typedef struct user_fpsimd_state fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.pc)) +#define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs.fpsr)) +#define ARCH_IOVEC_FOR_GETREGSET + +#elif defined(__powerpc64__) +typedef struct pt_regs regs_struct; +typedef elf_fpregset_t fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.nip)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t)fpregs[32]) +#define ARCH_IOVEC_FOR_GETREGSET + +#elif defined(__mips__) +typedef struct pt_regs regs_struct; +typedef elf_fpregset_t fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.cp0_epc)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t) (__fpregs[32])) +#define __PTRACE_FPREQUEST PTRACE_GETFPREGS + +#elif defined(__arm__) +# include +# include +typedef struct pt_regs regs_struct; +typedef char fpregs_struct[ARM_VFPREGS_SIZE]; +#define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.ARM_pc)) +#define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs + 32 * 8)) +#define __PTRACE_FPREQUEST PTRACE_GETVFPREGS +#endif + int main(void) { pid_t pid; @@ -21,28 +70,48 @@ int main(void) { execl("/bin/true", "true", NULL); } else { wait(NULL); - user_regs_struct regs; + regs_struct regs; + regs_struct* volatile pregs = ®s; +#ifdef ARCH_IOVEC_FOR_GETREGSET + struct iovec regset_io; +#endif int res; - user_regs_struct * volatile pregs = ®s; + #ifdef POSITIVE ++pregs; #endif - res = ptrace(PTRACE_GETREGS, pid, NULL, pregs); + +#ifdef ARCH_IOVEC_FOR_GETREGSET +# define __PTRACE_REQUEST PTRACE_GETREGSET +# define __PTRACE_ARGS (void*)NT_PRSTATUS, (void*)®set_io + regset_io.iov_base = pregs; + regset_io.iov_len = sizeof(regs_struct); +#else +# define __PTRACE_REQUEST PTRACE_GETREGS +# define __PTRACE_ARGS NULL, pregs +#endif + res = ptrace((enum __ptrace_request)__PTRACE_REQUEST, pid, __PTRACE_ARGS); // CHECK: AddressSanitizer: stack-buffer-overflow // CHECK: {{.*ptrace.cc:}}[[@LINE-2]] assert(!res); -#ifdef __x86_64__ - printf("%lx\n", (unsigned long)regs.rip); + PRINT_REG_PC(regs); + + fpregs_struct fpregs; +#ifdef ARCH_IOVEC_FOR_GETREGSET +# define __PTRACE_FPREQUEST PTRACE_GETREGSET +# define __PTRACE_FPARGS (void*)NT_PRSTATUS, (void*)®set_io + regset_io.iov_base = &fpregs; + regset_io.iov_len = sizeof(fpregs_struct); + res = ptrace((enum __ptrace_request)PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, + (void*)®set_io); #else - printf("%lx\n", regs.eip); +# define __PTRACE_FPARGS NULL, &fpregs #endif - - user_fpregs_struct fpregs; - res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs); + res = ptrace((enum __ptrace_request)__PTRACE_FPREQUEST, pid, __PTRACE_FPARGS); assert(!res); - printf("%lx\n", (unsigned long)fpregs.cwd); + PRINT_REG_FP(fpregs); -#ifndef __x86_64__ +#ifdef __i386__ user_fpxregs_struct fpxregs; res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs); assert(!res); diff --git a/test/asan/TestCases/Linux/stress_dtls.c b/test/asan/TestCases/Linux/stress_dtls.c index bbf4b3e0ef..fd1ce0cd47 100644 --- a/test/asan/TestCases/Linux/stress_dtls.c +++ b/test/asan/TestCases/Linux/stress_dtls.c @@ -1,4 +1,5 @@ // REQUIRES: asan-64-bits +// UNSUPPORTED: android // Stress test dynamic TLS + dlopen + threads. // // Note that glibc 2.15 seems utterly broken on this test, diff --git a/test/asan/TestCases/Posix/coverage-caller-callee.cc b/test/asan/TestCases/Posix/coverage-caller-callee.cc index 99cce23c3d..fb8b9bf92a 100644 --- a/test/asan/TestCases/Posix/coverage-caller-callee.cc +++ b/test/asan/TestCases/Posix/coverage-caller-callee.cc @@ -11,6 +11,7 @@ // RUN: rm -f caller-callee*.sancov // // REQUIRES: asan-64-bits +// UNSUPPORTED: android // // CHECK-10-1: CovDump: 10 caller-callee pairs written // CHECK-9-2: CovDump: 18 caller-callee pairs written diff --git a/test/asan/TestCases/contiguous_container.cc b/test/asan/TestCases/contiguous_container.cc index bda0f53dea..3f754562af 100644 --- a/test/asan/TestCases/contiguous_container.cc +++ b/test/asan/TestCases/contiguous_container.cc @@ -26,10 +26,18 @@ void TestContainer(size_t capacity) { for (size_t idx = size; idx < capacity; idx++) assert(__asan_address_is_poisoned(beg + idx)); assert(__sanitizer_verify_contiguous_container(beg, mid, end)); - if (mid != beg) + assert(NULL == + __sanitizer_contiguous_container_find_bad_address(beg, mid, end)); + if (mid != beg) { assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end)); - if (mid != end) + assert(mid - 1 == __sanitizer_contiguous_container_find_bad_address( + beg, mid - 1, end)); + } + if (mid != end) { assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end)); + assert(mid == __sanitizer_contiguous_container_find_bad_address( + beg, mid + 1, end)); + } } // Don't forget to unpoison the whole thing before destroing/reallocating. diff --git a/test/asan/TestCases/coverage-levels.cc b/test/asan/TestCases/coverage-levels.cc index effc9cdbd9..612bbd8377 100644 --- a/test/asan/TestCases/coverage-levels.cc +++ b/test/asan/TestCases/coverage-levels.cc @@ -16,7 +16,7 @@ // RUN: %env_asan_opts=coverage=1:coverage_pcs=0:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOPCS // // REQUIRES: asan-64-bits - +// UNSUPPORTED: android volatile int sink; int main(int argc, char **argv) { if (argc == 0) diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc index 4f148d8547..dcab69474a 100644 --- a/test/asan/TestCases/coverage-order-pcs.cc +++ b/test/asan/TestCases/coverage-order-pcs.cc @@ -20,6 +20,7 @@ // RUN: rm -rf $DIR // Ordering works only in 64-bit mode for now. // REQUIRES: asan-64-bits +// UNSUPPORTED: android #include void foo() { fprintf(stderr, "FOO\n"); } diff --git a/test/asan/TestCases/coverage-reset.cc b/test/asan/TestCases/coverage-reset.cc index 5c648cc95e..1f5eed4c85 100644 --- a/test/asan/TestCases/coverage-reset.cc +++ b/test/asan/TestCases/coverage-reset.cc @@ -3,6 +3,9 @@ // RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t // RUN: %env_asan_opts=coverage=1 %run %t +// https://github.com/google/sanitizers/issues/618 +// UNSUPPORTED: android + #include #include #include diff --git a/test/asan/TestCases/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc index b4b68a064f..b7755f847d 100644 --- a/test/asan/TestCases/coverage-tracing.cc +++ b/test/asan/TestCases/coverage-tracing.cc @@ -25,6 +25,7 @@ // RUN: rm -rf %T/coverage-tracing // // REQUIRES: asan-64-bits +// UNSUPPORTED: android #include volatile int sink; diff --git a/test/asan/TestCases/throw_call_test.cc b/test/asan/TestCases/throw_call_test.cc index 20e9a5ee56..4b3910dce1 100644 --- a/test/asan/TestCases/throw_call_test.cc +++ b/test/asan/TestCases/throw_call_test.cc @@ -23,12 +23,15 @@ void ReallyThrow() { __attribute__((noinline)) void Throw() { - int a, b, c, d, e; + int a, b, c, d, e, f, g, h; pretend_to_do_something(&a); pretend_to_do_something(&b); pretend_to_do_something(&c); pretend_to_do_something(&d); pretend_to_do_something(&e); + pretend_to_do_something(&f); + pretend_to_do_something(&g); + pretend_to_do_something(&h); fprintf(stderr, "Throw stack = %p\n", &a); ReallyThrow(); } @@ -37,9 +40,9 @@ __attribute__((noinline)) void CheckStack() { int ar[100]; pretend_to_do_something(ar); + fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); for (int i = 0; i < 100; i++) ar[i] = i; - fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); } int main(int argc, char** argv) { diff --git a/test/asan/android_commands/android_run.py b/test/asan/android_commands/android_run.py index 6bda6e96d2..272d2110e5 100755 --- a/test/asan/android_commands/android_run.py +++ b/test/asan/android_commands/android_run.py @@ -19,14 +19,14 @@ def build_env(): return ' '.join(args) is_64bit = (subprocess.check_output(['file', sys.argv[0] + '.real']).find('64-bit') != -1) -asanwrapper = "asanwrapper64" if is_64bit else "asanwrapper" +asanwrapper = "" if is_64bit else "asanwrapper " device_env = build_env() device_args = ' '.join(sys.argv[1:]) # FIXME: escape? device_stdout = device_binary + '.stdout' device_stderr = device_binary + '.stderr' device_exitcode = device_binary + '.exitcode' -ret = adb(['shell', 'cd %s && %s %s %s %s >%s 2>%s ; echo $? >%s' % +ret = adb(['shell', 'cd %s && %s %s%s %s >%s 2>%s ; echo $? >%s' % (ANDROID_TMPDIR, device_env, asanwrapper, device_binary, device_args, device_stdout, device_stderr, device_exitcode)]) if ret != 0: diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index e3e86bddbc..fd99f66996 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -60,7 +60,7 @@ else: # BFD linker in 64-bit android toolchains fails to find libm.so, which is a # transitive shared library dependency (via asan runtime). if config.android: - extra_linkflags += ["-fuse-ld=gold"] + extra_linkflags += ["-lm"] # Setup default compiler flags used with -fsanitize=address option. # FIXME: Review the set of required flags and check if it can be reduced. diff --git a/test/builtins/Unit/fixtfdi_test.c b/test/builtins/Unit/fixtfdi_test.c new file mode 100644 index 0000000000..cc25becb2f --- /dev/null +++ b/test/builtins/Unit/fixtfdi_test.c @@ -0,0 +1,71 @@ +//===--------------- fixtfdi_test.c - Test __fixtfdi ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixtfdi for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +di_int __fixtfdi(long double a); + +int test__fixtfdi(long double a, di_int expected) +{ + di_int x = __fixtfdi(a); + int ret = (x != expected); + + if (ret) + { + printf("error in test__fixtfdi(%.20Lf) = %llX, " + "expected %llX\n", a, x, expected); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixtfdi(makeInf128(), 0x7fffffffffffffffLL)) + return 1; + if (test__fixtfdi(0, 0x0)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp+5L, 0x24LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp-3L, 0x0LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+20L, 0x123456LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+40L, 0x123456789abLL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+60L, 0x123456789abcdef1LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp+256L, 0x7fffffffffffffffLL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+20L, 0xffffffffffedcbaaLL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+40L, 0xfffffedcba987655LL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+256L, 0x8000000000000000LL)) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} diff --git a/test/builtins/Unit/fixtfsi_test.c b/test/builtins/Unit/fixtfsi_test.c index 45ad0d2437..1da516bd07 100644 --- a/test/builtins/Unit/fixtfsi_test.c +++ b/test/builtins/Unit/fixtfsi_test.c @@ -54,7 +54,7 @@ int main() return 1; if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa)) return 1; - if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001)) + if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000000)) return 1; #else diff --git a/test/builtins/Unit/fixtfti_test.c b/test/builtins/Unit/fixtfti_test.c new file mode 100644 index 0000000000..52184ca624 --- /dev/null +++ b/test/builtins/Unit/fixtfti_test.c @@ -0,0 +1,83 @@ +//===--------------- fixtfti_test.c - Test __fixtfti ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixtfti for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +ti_int __fixtfti(long double a); + +int test__fixtfti(long double a, ti_int expected) +{ + ti_int x = __fixtfti(a); + int ret = (x != expected); + + if (ret) + { + twords xt; + xt.all = x; + + twords expectedt; + expectedt.all = expected; + + printf("error in test__fixtfti(%.20Lf) = 0x%.16llX%.16llX, " + "expected 0x%.16llX%.16llX\n", + a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixtfti(makeInf128(), make_ti(0x7fffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixtfti(0, make_ti(0x0LL, 0x0LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp+5L, make_ti(0x0LL, 0x24LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp-3L, make_ti(0x0LL, 0x0LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdef12345678p+20L, + make_ti(0x0LL, 0x123456LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdef123456789abcdep+112L, + make_ti(0x123456789abcdLL, 0xef123456789abcdeLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdef123456789abcdep+112L, + make_ti(0xFFFEDCBA98765432LL, 0x10EDCBA987654322LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp+256L, make_ti(0x7fffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdefp+20L, make_ti(0xffffffffffffffffLL, + 0xffffffffffedcbaaLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdefp+256L, make_ti(0x8000000000000000LL, + 0x0))) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} diff --git a/test/builtins/Unit/fixunsdfdi_test.c b/test/builtins/Unit/fixunsdfdi_test.c index 3998482876..1ddc5340b0 100644 --- a/test/builtins/Unit/fixunsdfdi_test.c +++ b/test/builtins/Unit/fixunsdfdi_test.c @@ -95,6 +95,9 @@ int main() if (test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800LL)) return 1; + if (test__fixunsdfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFFLL)) + return 1; + #if !TARGET_LIBGCC if (test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0)) return 1; diff --git a/test/builtins/Unit/fixunsdfsi_test.c b/test/builtins/Unit/fixunsdfsi_test.c index 551fc88a52..8d3d6304f4 100644 --- a/test/builtins/Unit/fixunsdfsi_test.c +++ b/test/builtins/Unit/fixunsdfsi_test.c @@ -75,6 +75,8 @@ int main() if (test__fixunsdfsi(0x1.000000p+31, 0x80000000)) return 1; + if (test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF)) + return 1; if (test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00)) return 1; if (test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80)) diff --git a/test/builtins/Unit/fixunsdfti_test.c b/test/builtins/Unit/fixunsdfti_test.c index e1aa56d763..0298fb9e94 100644 --- a/test/builtins/Unit/fixunsdfti_test.c +++ b/test/builtins/Unit/fixunsdfti_test.c @@ -115,6 +115,9 @@ int main() return 1; if (test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, make_ti(0x7FFFFFFFFFFFF800LL, 0))) return 1; + if (test__fixunsdfti(0x1.0000000000000p+128, make_ti(0xFFFFFFFFFFFFFFFFLL, + 0xFFFFFFFFFFFFFFFFLL))) + return 1; #if !TARGET_LIBGCC if (test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0)) diff --git a/test/builtins/Unit/fixunssfdi_test.c b/test/builtins/Unit/fixunssfdi_test.c index 812457a002..166153cb5b 100644 --- a/test/builtins/Unit/fixunssfdi_test.c +++ b/test/builtins/Unit/fixunssfdi_test.c @@ -79,6 +79,8 @@ int main() return 1; if (test__fixunssfdi(0x1.000000p+63F, 0x8000000000000000LL)) return 1; + if (test__fixunssfdi(0x1.000000p+64F, 0xFFFFFFFFFFFFFFFFLL)) + return 1; if (test__fixunssfdi(0x1.FFFFFEp+62F, 0x7FFFFF8000000000LL)) return 1; if (test__fixunssfdi(0x1.FFFFFCp+62F, 0x7FFFFF0000000000LL)) diff --git a/test/builtins/Unit/fixunssfsi_test.c b/test/builtins/Unit/fixunssfsi_test.c index 94a8b0867e..17293e4385 100644 --- a/test/builtins/Unit/fixunssfsi_test.c +++ b/test/builtins/Unit/fixunssfsi_test.c @@ -75,6 +75,8 @@ int main() if (test__fixunssfsi(0x1.000000p+31F, 0x80000000)) return 1; + if (test__fixunssfsi(0x1.000000p+32F, 0xFFFFFFFF)) + return 1; if (test__fixunssfsi(0x1.FFFFFEp+31F, 0xFFFFFF00)) return 1; if (test__fixunssfsi(0x1.FFFFFEp+30F, 0x7FFFFF80)) diff --git a/test/builtins/Unit/fixunstfdi_test.c b/test/builtins/Unit/fixunstfdi_test.c index 60ea503d27..817c59b2d5 100644 --- a/test/builtins/Unit/fixunstfdi_test.c +++ b/test/builtins/Unit/fixunstfdi_test.c @@ -13,14 +13,14 @@ #include -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ #include "int_lib.h" // Returns: convert a to a unsigned long long, rounding toward zero. // Negative values all become zero. -// Assumption: long double is a ppc 128 bit floating point type +// Assumption: long double is a 128 bit floating point type // du_int is a 64 bit integral type // value in long double is representable in du_int or is negative // (no range checking performed) @@ -44,7 +44,7 @@ char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; int main() { -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ if (test__fixunstfdi(0.0, 0)) return 1; @@ -107,6 +107,8 @@ int main() return 1; if (test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62L, 0x7FFFFFFFFFFFFFFELL)) return 1; + if (test__fixunstfdi(0x1.p+64L, 0xFFFFFFFFFFFFFFFFLL)) + return 1; if (test__fixunstfdi(-0x1.0000000000000000p+63L, 0)) return 1; diff --git a/test/builtins/Unit/fixunstfsi_test.c b/test/builtins/Unit/fixunstfsi_test.c index 4bf8fdec60..13ed779522 100644 --- a/test/builtins/Unit/fixunstfsi_test.c +++ b/test/builtins/Unit/fixunstfsi_test.c @@ -56,6 +56,9 @@ int main() if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0))) return 1; + if (test__fixunstfsi(0x1.p+32, 0xFFFFFFFFLL)) + return 1; + #else printf("skipped\n"); diff --git a/test/builtins/Unit/fixunstfti_test.c b/test/builtins/Unit/fixunstfti_test.c new file mode 100644 index 0000000000..60a0982b62 --- /dev/null +++ b/test/builtins/Unit/fixunstfti_test.c @@ -0,0 +1,103 @@ +//===-- fixunstfti_test.c - Test __fixunstfti -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixunstfti for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" +#include "int_lib.h" + +// Returns: convert a to a unsigned long long, rounding toward zero. +// Negative values all become zero. + +// Assumption: long double is a 128 bit floating point type +// tu_int is a 128 bit integral type +// value in long double is representable in tu_int or is negative +// (no range checking performed) + +COMPILER_RT_ABI tu_int __fixunstfti(long double a); + +int test__fixunstfti(long double a, tu_int expected) +{ + tu_int x = __fixunstfti(a); + if (x != expected) + { + twords xt; + xt.all = x; + + twords expectedt; + expectedt.all = expected; + + printf("error in __fixunstfti(%.20Lf) = 0x%.16llX%.16llX, " + "expected 0x%.16llX%.16llX\n", + a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); + } + return x != expected; +} + +char assumption_1[sizeof(tu_int) == 4*sizeof(su_int)] = {0}; +char assumption_2[sizeof(tu_int)*CHAR_BIT == 128] = {0}; +char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixunstfti(makeInf128(), make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + + if (test__fixunstfti(0.0, 0)) + return 1; + + if (test__fixunstfti(0.5, 0)) + return 1; + if (test__fixunstfti(0.99, 0)) + return 1; + if (test__fixunstfti(1.0, 1)) + return 1; + if (test__fixunstfti(1.5, 1)) + return 1; + if (test__fixunstfti(1.99, 1)) + return 1; + if (test__fixunstfti(2.0, 2)) + return 1; + if (test__fixunstfti(2.01, 2)) + return 1; + if (test__fixunstfti(-0.01, 0)) + return 1; + if (test__fixunstfti(-0.99, 0)) + return 1; + + if (test__fixunstfti(0x1.p+128, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + + if (test__fixunstfti(0x1.FFFFFEp+126, make_ti(0x7fffff8000000000LL, 0x0))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+127, make_ti(0xffffff0000000000LL, 0x0))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+128, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+129, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + +#else + printf("skipped\n"); +#endif + return 0; +} diff --git a/test/builtins/Unit/multf3_test.c b/test/builtins/Unit/multf3_test.c index 98a8f7a323..42147550c7 100644 --- a/test/builtins/Unit/multf3_test.c +++ b/test/builtins/Unit/multf3_test.c @@ -82,7 +82,7 @@ int main() return 1; // underflow if (test__multf3(0x1.23456734245345p-10000L, - 0x1.edcba524498724p-6383L, + 0x1.edcba524498724p-6497L, UINT64_C(0x0), UINT64_C(0x0))) return 1; diff --git a/test/msan/Linux/process_vm_readv.cc b/test/msan/Linux/process_vm_readv.cc index c52b5d0eda..601c0d247d 100644 --- a/test/msan/Linux/process_vm_readv.cc +++ b/test/msan/Linux/process_vm_readv.cc @@ -16,12 +16,9 @@ typedef ssize_t (*process_vm_readwritev_fn)(pid_t, const iovec *, unsigned long, int main(void) { // This requires glibc 2.15. - process_vm_readwritev_fn process_vm_readv = - (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_readv"); - process_vm_readwritev_fn process_vm_writev = - (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_writev"); - if (!process_vm_readv) { - assert(!process_vm_writev); + process_vm_readwritev_fn libc_process_vm_readv = + (process_vm_readwritev_fn)dlsym(RTLD_NEXT, "process_vm_readv"); + if (!libc_process_vm_readv) { // Exit with success, emulating the expected output. #ifdef POSITIVE printf("process_vm_readv not found!\n"); @@ -32,7 +29,11 @@ int main(void) { return 0; #endif } - assert(process_vm_readv && process_vm_writev); + + process_vm_readwritev_fn process_vm_readv = + (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_readv"); + process_vm_readwritev_fn process_vm_writev = + (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_writev"); char a[100]; memset(a, 0xab, 100); diff --git a/test/msan/chained_origin_limits.cc b/test/msan/chained_origin_limits.cc index 889d4ea853..90fd09a86b 100644 --- a/test/msan/chained_origin_limits.cc +++ b/test/msan/chained_origin_limits.cc @@ -61,10 +61,6 @@ // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out -// -// AArch64 fails with -fsanitize-memory-track-origins=2 with and invalid access -// on 'return buf[50]'. -// XFAIL: aarch64 #include #include diff --git a/test/msan/mmap.cc b/test/msan/mmap.cc index 962836cd65..27a8bb2d6e 100644 --- a/test/msan/mmap.cc +++ b/test/msan/mmap.cc @@ -23,17 +23,27 @@ bool AddrIsApp(void *p) { #elif defined(__powerpc64__) return addr < 0x000100000000ULL || addr >= 0x300000000000ULL; #elif defined(__aarch64__) - unsigned long vma = SystemVMA(); - if (vma == 39) - return (addr >= 0x5500000000ULL && addr < 0x5600000000ULL) || - (addr > 0x7000000000ULL); - else if (vma == 42) - return (addr >= 0x2aa00000000ULL && addr < 0x2ab00000000ULL) || - (addr > 0x3f000000000ULL); - else { - fprintf(stderr, "unsupported vma: %lu\n", vma); - exit(1); - } + + struct AddrMapping { + uintptr_t start; + uintptr_t end; + } mappings[] = { + {0x05000000000ULL, 0x06000000000ULL}, + {0x07000000000ULL, 0x08000000000ULL}, + {0x0F000000000ULL, 0x10000000000ULL}, + {0x11000000000ULL, 0x12000000000ULL}, + {0x20000000000ULL, 0x21000000000ULL}, + {0x2A000000000ULL, 0x2B000000000ULL}, + {0x2E000000000ULL, 0x2F000000000ULL}, + {0x3B000000000ULL, 0x3C000000000ULL}, + {0x3F000000000ULL, 0x40000000000ULL}, + }; + const size_t mappingsSize = sizeof (mappings) / sizeof (mappings[0]); + + for (int i=0; i= mappings[i].start && addr < mappings[i].end) + return true; + return false; #endif } diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc index 0594f00945..3066dd5b61 100644 --- a/test/msan/strlen_of_shadow.cc +++ b/test/msan/strlen_of_shadow.cc @@ -20,21 +20,7 @@ const char *mem_to_shadow(const char *p) { (((uintptr_t)(mem) & ~0x200000000000ULL) ^ 0x100000000000ULL) return (char *)(LINEARIZE_MEM(p) + 0x080000000000ULL); #elif defined(__aarch64__) - unsigned long vma = SystemVMA(); - -#define LINEARIZE_MEM_39(mem) \ - (((uintptr_t)(mem) & ~0x7C00000000ULL) ^ 0x100000000ULL) -#define LINEARIZE_MEM_42(mem) \ - (((uintptr_t)(mem) & ~0x3E000000000ULL) ^ 0x1000000000ULL) - - if (vma == 39) - return (char *)(LINEARIZE_MEM_39(p) + 0x4000000000ULL); - else if (vma == 42) - return (char *)(LINEARIZE_MEM_42(p) + 0x10000000000ULL); - else { - fprintf(stderr, "unsupported vma: %lu\n", vma); - exit(1); - } + return (char *)((uintptr_t)p ^ 0x6000000000ULL); #endif } diff --git a/test/sanitizer_common/TestCases/Linux/ptrace.cc b/test/sanitizer_common/TestCases/Linux/ptrace.cc index 561446620a..67b6474304 100644 --- a/test/sanitizer_common/TestCases/Linux/ptrace.cc +++ b/test/sanitizer_common/TestCases/Linux/ptrace.cc @@ -10,7 +10,7 @@ #include #include #include -#if __mips64 +#if __mips64 || __arm__ #include #include #endif @@ -43,23 +43,34 @@ int main(void) { printf("%x\n", fpregs.mxcsr); #endif // __x86_64__ -#if (__powerpc64__ || __mips64) +#if (__powerpc64__ || __mips64 || __arm__) struct pt_regs regs; res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); assert(!res); #if (__powerpc64__) if (regs.nip) printf("%lx\n", regs.nip); -#else +#elif (__mips64) if (regs.cp0_epc) printf("%lx\n", regs.cp0_epc); +#elif (__arm__) + if (regs.ARM_pc) + printf("%lx\n", regs.ARM_pc); #endif +#if (__powerpc64 || __mips64) elf_fpregset_t fpregs; res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); assert(!res); if ((elf_greg_t)fpregs[32]) // fpscr printf("%lx\n", (elf_greg_t)fpregs[32]); -#endif // (__powerpc64__ || __mips64) +#elif (__arm__) + char regbuf[ARM_VFPREGS_SIZE]; + res = ptrace((enum __ptrace_request)PTRACE_GETVFPREGS, pid, 0, regbuf); + assert(!res); + unsigned fpscr = *(unsigned*)(regbuf + (32 * 8)); + printf ("%x\n", fpscr); +#endif +#endif // (__powerpc64__ || __mips64 || __arm__) #if (__aarch64__) struct iovec regset_io; diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt index 6068556706..1492ddb64f 100644 --- a/test/tsan/CMakeLists.txt +++ b/test/tsan/CMakeLists.txt @@ -1,5 +1,5 @@ set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips") +if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips" AND NOT APPLE) list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) diff --git a/test/tsan/atomic_free3.cc b/test/tsan/atomic_free3.cc index 753671bd11..f2875aeb65 100644 --- a/test/tsan/atomic_free3.cc +++ b/test/tsan/atomic_free3.cc @@ -13,7 +13,7 @@ int main() { pthread_t t; pthread_create(&t, 0, Thread, a); while (__atomic_load_n(a, __ATOMIC_RELAXED) == 0) - pthread_yield(); + sched_yield(); delete a; pthread_join(t, 0); } diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg index 092fa43be3..b0c6671832 100644 --- a/test/tsan/lit.cfg +++ b/test/tsan/lit.cfg @@ -20,6 +20,11 @@ config.test_source_root = os.path.dirname(__file__) # Setup environment variables for running ThreadSanitizer. tsan_options = "atexit_sleep_ms=0" +if config.host_os == 'Darwin': + # On Darwin, we default to `abort_on_error=1`, which would make tests run + # much slower. Let's override this and run lit tests with 'abort_on_error=0'. + tsan_options += ':abort_on_error=0' + config.environment['TSAN_OPTIONS'] = tsan_options # GCC driver doesn't add necessary compile/link flags with -fsanitize=thread. @@ -34,7 +39,8 @@ clang_tsan_cflags = ["-fsanitize=thread", "-m64"] + config.debug_info_flags + extra_cflags clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags # Add additional flags if we're using instrumented libc++. -if config.has_libcxx: +# Instrumented libcxx currently not supported on Darwin. +if config.has_libcxx and config.host_os != 'Darwin': # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib", "tsan", "libcxx_tsan") @@ -60,8 +66,8 @@ config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__ # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] -# ThreadSanitizer tests are currently supported on FreeBSD and Linux only. -if config.host_os not in ['FreeBSD', 'Linux']: +# ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin. +if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']: config.unsupported = True # Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL diff --git a/test/tsan/real_deadlock_detector_stress_test.cc b/test/tsan/real_deadlock_detector_stress_test.cc index 67c878f450..5576f12589 100644 --- a/test/tsan/real_deadlock_detector_stress_test.cc +++ b/test/tsan/real_deadlock_detector_stress_test.cc @@ -59,7 +59,7 @@ void *Thread(void *seed) { for (;;) { int old = __atomic_load_n(&m->state, __ATOMIC_RELAXED); if (old == kStateLocked) { - pthread_yield(); + sched_yield(); continue; } int newv = old + 1; diff --git a/test/tsan/signal_errno.cc b/test/tsan/signal_errno.cc index 8305e84930..5354cdeeb7 100644 --- a/test/tsan/signal_errno.cc +++ b/test/tsan/signal_errno.cc @@ -24,7 +24,7 @@ static __attribute__((noinline)) void loop() { volatile char *p = (char*)malloc(1); p[0] = 0; free((void*)p); - pthread_yield(); + sched_yield(); } } diff --git a/test/tsan/test.h b/test/tsan/test.h index 6af33a139b..adc44bbe96 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -8,32 +8,29 @@ // TSan-invisible barrier. // Tests use it to establish necessary execution order in a way that does not // interfere with tsan (does not establish synchronization between threads). -__typeof(pthread_barrier_wait) *barrier_wait; +// 8 lsb is thread count, the remaining are count of entered threads. +typedef unsigned long long invisible_barrier_t; -void barrier_init(pthread_barrier_t *barrier, unsigned count) { -#if defined(__FreeBSD__) - static const char libpthread_name[] = "libpthread.so"; -#else - static const char libpthread_name[] = "libpthread.so.0"; -#endif +void barrier_init(invisible_barrier_t *barrier, unsigned count) { + if (count >= (1 << 8)) + exit(fprintf(stderr, "barrier_init: count is too large (%d)\n", count)); + *barrier = count; +} - if (barrier_wait == 0) { - void *h = dlopen(libpthread_name, RTLD_LAZY); - if (h == 0) { - fprintf(stderr, "failed to dlopen %s, exiting\n", libpthread_name); - exit(1); - } - barrier_wait = (__typeof(barrier_wait))dlsym(h, "pthread_barrier_wait"); - if (barrier_wait == 0) { - fprintf(stderr, "failed to resolve pthread_barrier_wait, exiting\n"); - exit(1); - } +void barrier_wait(invisible_barrier_t *barrier) { + unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED); + unsigned old_epoch = (old >> 8) / (old & 0xff); + for (;;) { + unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED); + unsigned cur_epoch = (cur >> 8) / (cur & 0xff); + if (cur_epoch != old_epoch) + return; + usleep(1000); } - pthread_barrier_init(barrier, 0, count); } // Default instance of the barrier, but a test can declare more manually. -pthread_barrier_t barrier; +invisible_barrier_t barrier; void print_address(void *address) { // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not match diff --git a/test/tsan/thread_name2.cc b/test/tsan/thread_name2.cc index a44f4b9d32..93387dab2b 100644 --- a/test/tsan/thread_name2.cc +++ b/test/tsan/thread_name2.cc @@ -6,7 +6,7 @@ #define pthread_setname_np pthread_set_name_np #endif -int Global; +long long Global; void *Thread1(void *x) { barrier_wait(&barrier); diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/coverage-levels.cc index 9e3a8b31c5..046d8868e4 100644 --- a/test/ubsan/TestCases/Misc/coverage-levels.cc +++ b/test/ubsan/TestCases/Misc/coverage-levels.cc @@ -38,4 +38,4 @@ int main(int argc, char **argv) { // to dump coverage. // CHECK1: 1 PCs written // CHECK2: 3 PCs written -// CHECK3: 4 PCs written +// CHECK3: 3 PCs written