Index: lib/tsan/CMakeLists.txt =================================================================== --- lib/tsan/CMakeLists.txt +++ lib/tsan/CMakeLists.txt @@ -151,6 +151,15 @@ add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_aarch64.S) elseif(arch MATCHES "powerpc64|powerpc64le") add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_ppc64.S) + # 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) elseif(arch MATCHES "mips64|mips64le") add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S) else() Index: lib/tsan/go/buildgo.sh =================================================================== --- lib/tsan/go/buildgo.sh +++ lib/tsan/go/buildgo.sh @@ -39,20 +39,37 @@ " if [ "`uname -a | grep Linux`" != "" ]; then - SUFFIX="linux_amd64" - OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Wno-unused-const-variable -Werror -Wno-unknown-warning-option" - OSLDFLAGS="-lpthread -fPIC -fpie" - SRCS=" - $SRCS - ../rtl/tsan_platform_linux.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_common.cc - ../../sanitizer_common/sanitizer_procmaps_linux.cc - ../../sanitizer_common/sanitizer_linux.cc - ../../sanitizer_common/sanitizer_linux_libcdep.cc - ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc - " + if [ "`uname -a | grep ppc64le`" != "" ]; then + SUFFIX="linux_ppc64le" + OSCFLAGS="-fPIC -Wno-maybe-uninitialized" + OSLDFLAGS="-lpthread -fPIC -fpie" + SRCS=" + $SRCS + ../rtl/tsan_platform_linux.cc + ../../sanitizer_common/sanitizer_posix.cc + ../../sanitizer_common/sanitizer_posix_libcdep.cc + ../../sanitizer_common/sanitizer_procmaps_common.cc + ../../sanitizer_common/sanitizer_procmaps_linux.cc + ../../sanitizer_common/sanitizer_linux.cc + ../../sanitizer_common/sanitizer_linux_libcdep.cc + ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc + " + elif [ "`uname -a | grep x86_64`" != "" ]; then + SUFFIX="linux_amd64" + OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Wno-unused-const-variable -Werror -Wno-unknown-warning-option" + OSLDFLAGS="-lpthread -fPIC -fpie" + SRCS=" + $SRCS + ../rtl/tsan_platform_linux.cc + ../../sanitizer_common/sanitizer_posix.cc + ../../sanitizer_common/sanitizer_posix_libcdep.cc + ../../sanitizer_common/sanitizer_procmaps_common.cc + ../../sanitizer_common/sanitizer_procmaps_linux.cc + ../../sanitizer_common/sanitizer_linux.cc + ../../sanitizer_common/sanitizer_linux_libcdep.cc + ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc + " + fi elif [ "`uname -a | grep FreeBSD`" != "" ]; then SUFFIX="freebsd_amd64" OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" @@ -132,7 +149,11 @@ FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -std=c++11 -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO=1 -DSANITIZER_DEADLOCK_DETECTOR_VERSION=2 $OSCFLAGS" if [ "$DEBUG" = "" ]; then - FLAGS="$FLAGS -DSANITIZER_DEBUG=0 -O3 -msse3 -fomit-frame-pointer" + if [ "$SUFFIX" = "linux_ppc64le" ]; then + FLAGS="$FLAGS -DSANITIZER_DEBUG=0 -O3 -mcpu=power8 -fomit-frame-pointer -fno-function-sections" + elif [ "$SUFFIX" = "linux_amd64" ]; then + FLAGS="$FLAGS -DSANITIZER_DEBUG=0 -O3 -msse3 -fomit-frame-pointer" + fi else FLAGS="$FLAGS -DSANITIZER_DEBUG=1 -g" fi Index: lib/tsan/rtl/tsan_platform.h =================================================================== --- lib/tsan/rtl/tsan_platform.h +++ lib/tsan/rtl/tsan_platform.h @@ -355,9 +355,9 @@ #define TSAN_RUNTIME_VMA 1 #endif -#elif SANITIZER_GO && !SANITIZER_WINDOWS +#elif SANITIZER_GO && !SANITIZER_WINDOWS && defined(__x86_64__) -/* Go on linux, darwin and freebsd +/* Go on linux, darwin and freebsd on x86_64 0000 0000 1000 - 0000 1000 0000: executable 0000 1000 0000 - 00c0 0000 0000: - 00c0 0000 0000 - 00e0 0000 0000: heap @@ -406,6 +406,107 @@ static const uptr kAppMemEnd = 0x00e000000000ull; }; +#elif SANITIZER_GO && defined(__powerpc64__) + +/* Go on linux/powerpc64 (44-bit VMA) +0000 0000 0100 - 0001 0000 0000: main binary +0001 0000 0000 - 0001 0000 0000: - +0001 0000 0000 - 0b00 0000 0000: shadow +0b00 0000 0000 - 0b00 0000 0000: - +0b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects) +0d00 0000 0000 - 0d00 0000 0000: - +0d00 0000 0000 - 0f00 0000 0000: traces +0f00 0000 0000 - 0f00 0000 0000: - +0f00 0000 0000 - 0f50 0000 0000: heap +0f50 0000 0000 - 0f60 0000 0000: - +0f60 0000 0000 - 1000 0000 0000: modules and main thread stack +*/ + +struct Mapping44 { + static const uptr kMetaShadowBeg = 0x0b0000000000ull; + static const uptr kMetaShadowEnd = 0x0d0000000000ull; + static const uptr kTraceMemBeg = 0x0d0000000000ull; + static const uptr kTraceMemEnd = 0x0f0000000000ull; + static const uptr kShadowBeg = 0x000100000000ull; + static const uptr kShadowEnd = 0x0b0000000000ull; + static const uptr kLoAppMemBeg = 0x000000000100ull; + static const uptr kLoAppMemEnd = 0x000100000000ull; + static const uptr kHeapMemBeg = 0x0f0000000000ull; + static const uptr kHeapMemEnd = 0x0f5000000000ull; + static const uptr kHiAppMemBeg = 0x0f6000000000ull; + static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits + static const uptr kAppMemMsk = 0x0f0000000000ull; + static const uptr kAppMemXor = 0x002100000000ull; + static const uptr kVdsoBeg = 0x3c0000000000000ull; +}; + +/* Go on linux/powerpc64 (46-bit VMA) +0000 0000 1000 - 0100 0000 0000: main binary +0100 0000 0000 - 0200 0000 0000: - +0100 0000 0000 - 1000 0000 0000: shadow +1000 0000 0000 - 1000 0000 0000: - +1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects) +2000 0000 0000 - 2000 0000 0000: - +2000 0000 0000 - 2200 0000 0000: traces +2200 0000 0000 - 3d00 0000 0000: - +3d00 0000 0000 - 3e00 0000 0000: heap +3e00 0000 0000 - 3e80 0000 0000: - +3e80 0000 0000 - 4000 0000 0000: modules and main thread stack +*/ + +struct Mapping46 { + static const uptr kMetaShadowBeg = 0x100000000000ull; + static const uptr kMetaShadowEnd = 0x200000000000ull; + static const uptr kTraceMemBeg = 0x200000000000ull; + static const uptr kTraceMemEnd = 0x220000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x3d0000000000ull; + static const uptr kHeapMemEnd = 0x3e0000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x010000000000ull; + static const uptr kHiAppMemBeg = 0x3e8000000000ull; + static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits + static const uptr kAppMemMsk = 0x3c0000000000ull; + static const uptr kAppMemXor = 0x020000000000ull; + static const uptr kVdsoBeg = 0x7800000000000000ull; +}; + +/* Go on linux/powerpc64 (47-bit VMA) +0000 0000 1000 - 0100 0000 0000: main binary +0100 0000 0000 - 0200 0000 0000: - +0100 0000 0000 - 1000 0000 0000: shadow +1000 0000 0000 - 1000 0000 0000: - +1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects) +2000 0000 0000 - 2000 0000 0000: - +2000 0000 0000 - 2200 0000 0000: traces +2200 0000 0000 - 7d00 0000 0000: - +7d00 0000 0000 - 7e00 0000 0000: heap +7e00 0000 0000 - 7e80 0000 0000: - +7e80 0000 0000 - 8000 0000 0000: modules and main thread stack +*/ + +struct Mapping47 { + static const uptr kMetaShadowBeg = 0x100000000000ull; + static const uptr kMetaShadowEnd = 0x200000000000ull; + static const uptr kTraceMemBeg = 0x200000000000ull; + static const uptr kTraceMemEnd = 0x220000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x7d0000000000ull; + static const uptr kHeapMemEnd = 0x7e0000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x010000000000ull; + static const uptr kHiAppMemBeg = 0x7e8000000000ull; + static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits + static const uptr kAppMemMsk = 0x7c0000000000ull; + static const uptr kAppMemXor = 0x020000000000ull; + static const uptr kVdsoBeg = 0x7800000000000000ull; +}; + +// Indicates the runtime will define the memory regions at runtime. +#define TSAN_RUNTIME_VMA 1 + #else # error "Unknown platform" #endif @@ -454,8 +555,15 @@ case MAPPING_HEAP_END: return Mapping::kHeapMemEnd; case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg; #else +# if defined(__powerpc64__) + case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg; + case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd; + case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg; + case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd; +# else case MAPPING_APP_BEG: return Mapping::kAppMemBeg; case MAPPING_APP_END: return Mapping::kAppMemEnd; +# endif #endif case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg; case MAPPING_SHADOW_END: return Mapping::kShadowEnd; @@ -534,7 +642,25 @@ } #else +# if defined(__powerpc64__) +ALWAYS_INLINE +uptr LoAppMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr LoAppMemEnd(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr HiAppMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr HiAppMemEnd(void) { + return MappingArchImpl(); +} +# else ALWAYS_INLINE uptr AppMemBeg(void) { return MappingArchImpl(); @@ -543,7 +669,7 @@ uptr AppMemEnd(void) { return MappingArchImpl(); } - +# endif #endif static inline @@ -571,10 +697,21 @@ return true; # endif #else +# if defined(__powerpc64__) + case 0: + *start = LoAppMemBeg(); + *end = LoAppMemEnd(); + return true; + case 1: + *start = HiAppMemBeg(); + *end = HiAppMemEnd(); + return true; +# else case 0: *start = AppMemBeg(); *end = AppMemEnd(); return true; +# endif #endif } } @@ -617,7 +754,12 @@ (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) || (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd); #else +# if defined(__powerpc64__) + return (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) || + (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd); +# else return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd; +# endif #endif } @@ -710,8 +852,13 @@ return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1))) ^ Mapping::kAppMemXor) * kShadowCnt; #else -# ifndef SANITIZER_WINDOWS +# if !SANITIZER_WINDOWS +# if defined(__x86_64__) return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg; +# elif defined(__powerpc64__) + return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1))) + ^ Mapping::kAppMemXor) * kShadowCnt; +# endif # else return ((x & ~(kShadowCell - 1)) * kShadowCnt) + Mapping::kShadowBeg; # endif @@ -749,7 +896,7 @@ return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) / kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); #else -# ifndef SANITIZER_WINDOWS +# if !SANITIZER_WINDOWS return (u32*)(((x & ~(kMetaShadowCell - 1)) / \ kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); # else @@ -805,8 +952,16 @@ # endif return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk; #else // #if !SANITIZER_GO -# ifndef SANITIZER_WINDOWS +# if !SANITIZER_WINDOWS +# if defined(__powerpc64__) + uptr p = (s / kShadowCnt) ^ Mapping::kAppMemXor; + if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd && + MemToShadow(p) == s) + return p; + return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk; +# else return (s & ~Mapping::kShadowBeg) / kShadowCnt; +# endif // (__powerpc64__) # else return (s - Mapping::kShadowBeg) / kShadowCnt; # endif // SANITIZER_WINDOWS Index: lib/tsan/rtl/tsan_platform_linux.cc =================================================================== --- lib/tsan/rtl/tsan_platform_linux.cc +++ lib/tsan/rtl/tsan_platform_linux.cc @@ -106,8 +106,15 @@ else if (p >= HiAppMemBeg() && p < HiAppMemEnd()) mem[file ? MemFile : MemMmap] += rss; #else +# if defined(__powerpc64__) + else if (p >= LoAppMemBeg() && p < LoAppMemEnd()) + mem[file ? MemFile : MemMmap] += rss; + else if (p >= HiAppMemBeg() && p < HiAppMemEnd()) + mem[file ? MemFile : MemMmap] += rss; +# else else if (p >= AppMemBeg() && p < AppMemEnd()) mem[file ? MemFile : MemMmap] += rss; +# endif #endif else if (p >= TraceMemBeg() && p < TraceMemEnd()) mem[MemTrace] += rss; @@ -207,22 +214,36 @@ #endif // #if !SANITIZER_GO void InitializePlatformEarly() { -#ifdef TSAN_RUNTIME_VMA +#if !SANITIZER_GO +# ifdef TSAN_RUNTIME_VMA vmaSize = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); -#if defined(__aarch64__) +# if defined(__aarch64__) if (vmaSize != 39 && vmaSize != 42 && vmaSize != 48) { Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); Printf("FATAL: Found %d - Supported 39, 42 and 48\n", vmaSize); Die(); } -#elif defined(__powerpc64__) +# elif defined(__powerpc64__) if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) { Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); Printf("FATAL: Found %d - Supported 44, 46, and 47\n", vmaSize); Die(); } -#endif +# endif +# endif +#else +# ifdef TSAN_RUNTIME_VMA +# if defined(__powerpc64__) + vmaSize = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); + if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 44, 46, and 47\n", int(vmaSize)); + Die(); + } +# endif +# endif #endif }