Index: lib/tsan/CMakeLists.txt =================================================================== --- lib/tsan/CMakeLists.txt +++ lib/tsan/CMakeLists.txt @@ -152,6 +152,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,12 @@ 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" + FLAGS="$FLAGS -DSANITIZER_DEBUG=0 -O3 -fomit-frame-pointer" + if [ "$SUFFIX" = "linux_ppc64le" ]; then + FLAGS="$FLAGS -mcpu=power8 -fno-function-sections" + elif [ "$SUFFIX" = "linux_amd64" ]; then + FLAGS="$FLAGS -msse3" + 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,75 @@ static const uptr kAppMemEnd = 0x00e000000000ull; }; +#elif SANITIZER_GO && defined(__powerpc64__) + +/* Only Mapping46 and Mapping47 are currently supported for powercp64 on Go. */ + +/* Go on linux/powerpc64 (46-bit VMA) +0000 1000 0000 - 00c0 0000 0000: main Go binary + Go heap +00c0 0000 0000 - 0200 0000 0000: - +2000 0000 0000 - 3000 0000 0000: shadow +3000 0000 0000 - 3000 0000 0000: - +3000 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects) +3400 0000 0000 - 3600 0000 0000: traces +3600 0000 0000 - 3dc0 0000 0000: - +3dc0 0000 0000 - 3e00 0000 0000: heap for C/C++ +3e00 0000 0000 - 3e80 0000 0000: - +3e80 0000 0000 - 4000 0000 0000: dyn loaded modules and their thread stack +*/ + +struct Mapping46 { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x340000000000ull; + static const uptr kTraceMemBeg = 0x340000000000ull; + static const uptr kTraceMemEnd = 0x360000000000ull; + static const uptr kShadowBeg = 0x200000000000ull; + static const uptr kShadowEnd = 0x300000000000ull; + static const uptr kHeapMemBeg = 0x3dc000000000ull; + static const uptr kHeapMemEnd = 0x3e0000000000ull; + static const uptr kLoAppMemBeg = 0x000010000000ull; + static const uptr kLoAppMemEnd = 0x020000000000ull; + static const uptr kHiAppMemBeg = 0x3e8000000000ull; + static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits + static const uptr kAppMemMsk = 0x3c0000000000ull; + static const uptr kAppMemXor = 0x080000000000ull; + static const uptr kVdsoBeg = 0x7800000000000000ull; +}; + +/* Go on linux/powerpc64 (47-bit VMA) +0000 1000 0000 - 00c0 0000 0000: main Go binary + Go heap +00c0 0000 0000 - 0200 0000 0000: - +2000 0000 0000 - 3000 0000 0000: shadow +3000 0000 0000 - 3000 0000 0000: - +3000 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects) +3400 0000 0000 - 3600 0000 0000: traces +3600 0000 0000 - 7d00 0000 0000: - +7d00 0000 0000 - 7e00 0000 0000: heap for C/C++ +7e00 0000 0000 - 7e80 0000 0000: - +7e80 0000 0000 - 8000 0000 0000: dyn loaded modules and their thread stack +*/ + +struct Mapping47 { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x340000000000ull; + static const uptr kTraceMemBeg = 0x340000000000ull; + static const uptr kTraceMemEnd = 0x360000000000ull; + static const uptr kShadowBeg = 0x200000000000ull; + static const uptr kShadowEnd = 0x300000000000ull; + 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 = 0x080000000000ull; + 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 +523,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; @@ -478,7 +554,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return MappingImpl(); +#endif case 46: return MappingImpl(); case 47: return MappingImpl(); } @@ -534,7 +612,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 +639,7 @@ uptr AppMemEnd(void) { return MappingArchImpl(); } - +# endif #endif static inline @@ -571,10 +667,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 +724,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 } @@ -633,7 +745,9 @@ return false; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return IsAppMemImpl(mem); +#endif case 46: return IsAppMemImpl(mem); case 47: return IsAppMemImpl(mem); } @@ -662,7 +776,9 @@ return false; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return IsShadowMemImpl(mem); +#endif case 46: return IsShadowMemImpl(mem); case 47: return IsShadowMemImpl(mem); } @@ -691,7 +807,9 @@ return false; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return IsMetaMemImpl(mem); +#endif case 46: return IsMetaMemImpl(mem); case 47: return IsMetaMemImpl(mem); } @@ -710,8 +828,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 @@ -730,7 +853,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return MemToShadowImpl(x); +#endif case 46: return MemToShadowImpl(x); case 47: return MemToShadowImpl(x); } @@ -749,7 +874,11 @@ return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) / kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); #else -# ifndef SANITIZER_WINDOWS +# if !SANITIZER_WINDOWS +# if defined(__powerpc64__) + return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) / + kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); +# endif return (u32*)(((x & ~(kMetaShadowCell - 1)) / \ kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); # else @@ -771,7 +900,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return MemToMetaImpl(x); +#endif case 46: return MemToMetaImpl(x); case 47: return MemToMetaImpl(x); } @@ -805,10 +936,20 @@ # 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; + p = p + (Mapping::kHiAppMemBeg & Mapping::kAppMemMsk); + if (p >= Mapping::kHiAppMemBeg && p < Mapping::kHiAppMemEnd && + MemToShadow(p) == s) + return p; + return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk; +# else return (s & ~Mapping::kShadowBeg) / kShadowCnt; -# else - return (s - Mapping::kShadowBeg) / kShadowCnt; +# endif # endif // SANITIZER_WINDOWS #endif } @@ -825,7 +966,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return ShadowToMemImpl(s); +#endif case 46: return ShadowToMemImpl(s); case 47: return ShadowToMemImpl(s); } @@ -862,7 +1005,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return GetThreadTraceImpl(tid); +#endif case 46: return GetThreadTraceImpl(tid); case 47: return GetThreadTraceImpl(tid); } @@ -894,7 +1039,9 @@ return 0; #elif defined(__powerpc64__) switch (vmaSize) { +#if !SANITIZER_GO case 44: return GetThreadTraceHeaderImpl(tid); +#endif case 46: return GetThreadTraceHeaderImpl(tid); case 47: return GetThreadTraceHeaderImpl(tid); } 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 != 46 && vmaSize != 47) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 46, 47 only with go \n", int (vmaSize)); + Die(); + } +# endif +# endif #endif } Index: lib/tsan/rtl/tsan_rtl.cc =================================================================== --- lib/tsan/rtl/tsan_rtl.cc +++ lib/tsan/rtl/tsan_rtl.cc @@ -306,8 +306,11 @@ const uptr m = (uptr)MemToMeta(p); VPrintf(3, " checking pointer %p: shadow=%p meta=%p\n", p, s, m); CHECK(IsAppMem(p)); + VPrintf(3, " p: %p s: %p \n", p, s); CHECK(IsShadowMem(s)); + VPrintf(3, " s: %p ShadowToMem(s): %p\n", s, ShadowToMem(s)); CHECK_EQ(p, ShadowToMem(s)); + VPrintf(3, " p: %p MemToMeta(p): %p\n", p, MemToMeta(p)); CHECK(IsMetaMem(m)); if (prev) { // Ensure that shadow and meta mappings are linear within a single