diff options
Diffstat (limited to 'contrib/compiler-rt/lib/tsan/go')
-rw-r--r-- | contrib/compiler-rt/lib/tsan/go/build.bat | 4 | ||||
-rwxr-xr-x | contrib/compiler-rt/lib/tsan/go/buildgo.sh | 103 | ||||
-rw-r--r-- | contrib/compiler-rt/lib/tsan/go/test.c | 65 | ||||
-rw-r--r-- | contrib/compiler-rt/lib/tsan/go/tsan_go.cc | 218 |
4 files changed, 390 insertions, 0 deletions
diff --git a/contrib/compiler-rt/lib/tsan/go/build.bat b/contrib/compiler-rt/lib/tsan/go/build.bat new file mode 100644 index 0000000..8f8087f --- /dev/null +++ b/contrib/compiler-rt/lib/tsan/go/build.bat @@ -0,0 +1,4 @@ +type tsan_go.cc ..\rtl\tsan_interface_atomic.cc ..\rtl\tsan_clock.cc ..\rtl\tsan_flags.cc ..\rtl\tsan_md5.cc ..\rtl\tsan_mutex.cc ..\rtl\tsan_report.cc ..\rtl\tsan_rtl.cc ..\rtl\tsan_rtl_mutex.cc ..\rtl\tsan_rtl_report.cc ..\rtl\tsan_rtl_thread.cc ..\rtl\tsan_stat.cc ..\rtl\tsan_suppressions.cc ..\rtl\tsan_sync.cc ..\rtl\tsan_stack_trace.cc ..\..\sanitizer_common\sanitizer_allocator.cc ..\..\sanitizer_common\sanitizer_common.cc ..\..\sanitizer_common\sanitizer_flags.cc ..\..\sanitizer_common\sanitizer_stacktrace.cc ..\..\sanitizer_common\sanitizer_libc.cc ..\..\sanitizer_common\sanitizer_printf.cc ..\..\sanitizer_common\sanitizer_suppressions.cc ..\..\sanitizer_common\sanitizer_thread_registry.cc ..\rtl\tsan_platform_windows.cc ..\..\sanitizer_common\sanitizer_win.cc ..\..\sanitizer_common\sanitizer_deadlock_detector1.cc ..\..\sanitizer_common\sanitizer_stackdepot.cc ..\..\sanitizer_common\sanitizer_persistent_allocator.cc > gotsan.cc + +gcc -c -o race_windows_amd64.syso gotsan.cc -I..\rtl -I..\.. -I..\..\sanitizer_common -I..\..\..\include -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 -Wno-error=attributes -Wno-attributes -Wno-format -DTSAN_DEBUG=0 -O3 -fomit-frame-pointer + diff --git a/contrib/compiler-rt/lib/tsan/go/buildgo.sh b/contrib/compiler-rt/lib/tsan/go/buildgo.sh new file mode 100755 index 0000000..4df2e96 --- /dev/null +++ b/contrib/compiler-rt/lib/tsan/go/buildgo.sh @@ -0,0 +1,103 @@ +set -e + +SRCS=" + tsan_go.cc + ../rtl/tsan_clock.cc + ../rtl/tsan_flags.cc + ../rtl/tsan_interface_atomic.cc + ../rtl/tsan_md5.cc + ../rtl/tsan_mutex.cc + ../rtl/tsan_report.cc + ../rtl/tsan_rtl.cc + ../rtl/tsan_rtl_mutex.cc + ../rtl/tsan_rtl_report.cc + ../rtl/tsan_rtl_thread.cc + ../rtl/tsan_stack_trace.cc + ../rtl/tsan_stat.cc + ../rtl/tsan_suppressions.cc + ../rtl/tsan_sync.cc + ../../sanitizer_common/sanitizer_allocator.cc + ../../sanitizer_common/sanitizer_common.cc + ../../sanitizer_common/sanitizer_deadlock_detector2.cc + ../../sanitizer_common/sanitizer_flags.cc + ../../sanitizer_common/sanitizer_libc.cc + ../../sanitizer_common/sanitizer_persistent_allocator.cc + ../../sanitizer_common/sanitizer_printf.cc + ../../sanitizer_common/sanitizer_suppressions.cc + ../../sanitizer_common/sanitizer_thread_registry.cc + ../../sanitizer_common/sanitizer_stackdepot.cc + ../../sanitizer_common/sanitizer_stacktrace.cc + ../../sanitizer_common/sanitizer_symbolizer.cc +" + +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+=" + ../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_stoptheworld_linux_libcdep.cc + " +elif [ "`uname -a | grep FreeBSD`" != "" ]; then + SUFFIX="freebsd_amd64" + OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" + OSLDFLAGS="-lpthread -fPIC -fpie" + 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_freebsd.cc + ../../sanitizer_common/sanitizer_linux.cc + ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc + " +elif [ "`uname -a | grep Darwin`" != "" ]; then + SUFFIX="darwin_amd64" + OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option" + OSLDFLAGS="-lpthread -fPIC -fpie" + SRCS+=" + ../rtl/tsan_platform_mac.cc + ../../sanitizer_common/sanitizer_mac.cc + ../../sanitizer_common/sanitizer_posix.cc + ../../sanitizer_common/sanitizer_posix_libcdep.cc + ../../sanitizer_common/sanitizer_procmaps_mac.cc + " +elif [ "`uname -a | grep MINGW`" != "" ]; then + SUFFIX="windows_amd64" + OSCFLAGS="-Wno-error=attributes -Wno-attributes -Wno-unused-const-variable -Wno-unknown-warning-option" + OSLDFLAGS="" + SRCS+=" + ../rtl/tsan_platform_windows.cc + ../../sanitizer_common/sanitizer_win.cc + " +else + echo Unknown platform + exit 1 +fi + +SRCS+=$ADD_SRCS + +rm -f gotsan.cc +for F in $SRCS; do + cat $F >> gotsan.cc +done + +FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -std=c++11 -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 -DSANITIZER_DEADLOCK_DETECTOR_VERSION=2 $OSCFLAGS" +if [ "$DEBUG" == "" ]; then + FLAGS+=" -DTSAN_DEBUG=0 -O3 -msse3 -fomit-frame-pointer" +else + FLAGS+=" -DTSAN_DEBUG=1 -g" +fi + +CC=${CC:-gcc} + +echo $CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS +$CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS + +$CC test.c race_$SUFFIX.syso -m64 -o test $OSLDFLAGS +GORACE="exitcode=0 atexit_sleep_ms=0" ./test diff --git a/contrib/compiler-rt/lib/tsan/go/test.c b/contrib/compiler-rt/lib/tsan/go/test.c new file mode 100644 index 0000000..94433f1 --- /dev/null +++ b/contrib/compiler-rt/lib/tsan/go/test.c @@ -0,0 +1,65 @@ +//===-- test.c ------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Sanity test for Go runtime. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +void __tsan_init(void **thr, void (*cb)(void*)); +void __tsan_fini(); +void __tsan_map_shadow(void *addr, unsigned long size); +void __tsan_go_start(void *thr, void **chthr, void *pc); +void __tsan_go_end(void *thr); +void __tsan_read(void *thr, void *addr, void *pc); +void __tsan_write(void *thr, void *addr, void *pc); +void __tsan_func_enter(void *thr, void *pc); +void __tsan_func_exit(void *thr); +void __tsan_malloc(void *p, unsigned long sz); +void __tsan_acquire(void *thr, void *addr); +void __tsan_release(void *thr, void *addr); +void __tsan_release_merge(void *thr, void *addr); + +void symbolize_cb(void *ctx) {} + +char buf0[100<<10]; + +void foobar() {} +void barfoo() {} + +int main(void) { + void *thr0 = 0; + char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1)); + __tsan_malloc(buf, 10); + __tsan_init(&thr0, symbolize_cb); + __tsan_map_shadow(buf, 4096); + __tsan_func_enter(thr0, (char*)&main + 1); + __tsan_malloc(buf, 10); + __tsan_release(thr0, buf); + __tsan_release_merge(thr0, buf); + void *thr1 = 0; + __tsan_go_start(thr0, &thr1, (char*)&barfoo + 1); + void *thr2 = 0; + __tsan_go_start(thr0, &thr2, (char*)&barfoo + 1); + __tsan_func_enter(thr1, (char*)&foobar + 1); + __tsan_func_enter(thr1, (char*)&foobar + 1); + __tsan_write(thr1, buf, (char*)&barfoo + 1); + __tsan_acquire(thr1, buf); + __tsan_func_exit(thr1); + __tsan_func_exit(thr1); + __tsan_go_end(thr1); + __tsan_func_enter(thr2, (char*)&foobar + 1); + __tsan_read(thr2, buf, (char*)&barfoo + 1); + __tsan_func_exit(thr2); + __tsan_go_end(thr2); + __tsan_func_exit(thr0); + __tsan_fini(); + return 0; +} diff --git a/contrib/compiler-rt/lib/tsan/go/tsan_go.cc b/contrib/compiler-rt/lib/tsan/go/tsan_go.cc new file mode 100644 index 0000000..cccf72c --- /dev/null +++ b/contrib/compiler-rt/lib/tsan/go/tsan_go.cc @@ -0,0 +1,218 @@ +//===-- tsan_go.cc --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ThreadSanitizer runtime for Go language. +// +//===----------------------------------------------------------------------===// + +#include "tsan_rtl.h" +#include "tsan_symbolize.h" +#include "sanitizer_common/sanitizer_common.h" +#include <stdlib.h> + +namespace __tsan { + +void InitializeInterceptors() { +} + +void InitializeDynamicAnnotations() { +} + +bool IsExpectedReport(uptr addr, uptr size) { + return false; +} + +void *internal_start_thread(void(*func)(void*), void *arg) { + return 0; +} + +void internal_join_thread(void *th) { +} + +ReportLocation *SymbolizeData(uptr addr) { + return 0; +} + +void *internal_alloc(MBlockType typ, uptr sz) { + return InternalAlloc(sz); +} + +void internal_free(void *p) { + InternalFree(p); +} + +struct SymbolizeContext { + uptr pc; + char *func; + char *file; + uptr line; + uptr off; + uptr res; +}; + +// Callback into Go. +static void (*symbolize_cb)(SymbolizeContext *ctx); + +SymbolizedStack *SymbolizeCode(uptr addr) { + SymbolizedStack *s = SymbolizedStack::New(addr); + SymbolizeContext ctx; + internal_memset(&ctx, 0, sizeof(ctx)); + ctx.pc = addr; + symbolize_cb(&ctx); + if (ctx.res) { + AddressInfo &info = s->info; + info.module_offset = ctx.off; + info.function = internal_strdup(ctx.func ? ctx.func : "??"); + info.file = internal_strdup(ctx.file ? ctx.file : "-"); + info.line = ctx.line; + info.column = 0; + } + return s; +} + +extern "C" { + +static ThreadState *main_thr; +static bool inited; + +static ThreadState *AllocGoroutine() { + ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, + sizeof(ThreadState)); + internal_memset(thr, 0, sizeof(*thr)); + return thr; +} + +void __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) { + symbolize_cb = cb; + ThreadState *thr = AllocGoroutine(); + main_thr = *thrp = thr; + Initialize(thr); + inited = true; +} + +void __tsan_fini() { + // FIXME: Not necessary thread 0. + ThreadState *thr = main_thr; + int res = Finalize(thr); + exit(res); +} + +void __tsan_map_shadow(uptr addr, uptr size) { + MapShadow(addr, size); +} + +void __tsan_read(ThreadState *thr, void *addr, void *pc) { + MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); +} + +void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { + if (callpc != 0) + FuncEntry(thr, callpc); + MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); + if (callpc != 0) + FuncExit(thr); +} + +void __tsan_write(ThreadState *thr, void *addr, void *pc) { + MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); +} + +void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { + if (callpc != 0) + FuncEntry(thr, callpc); + MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); + if (callpc != 0) + FuncExit(thr); +} + +void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) { + MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false); +} + +void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) { + MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); +} + +void __tsan_func_enter(ThreadState *thr, void *pc) { + FuncEntry(thr, (uptr)pc); +} + +void __tsan_func_exit(ThreadState *thr) { + FuncExit(thr); +} + +void __tsan_malloc(void *p, uptr sz) { + if (!inited) + return; + MemoryResetRange(0, 0, (uptr)p, sz); +} + +void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { + ThreadState *thr = AllocGoroutine(); + *pthr = thr; + int goid = ThreadCreate(parent, (uptr)pc, 0, true); + ThreadStart(thr, goid, 0); +} + +void __tsan_go_end(ThreadState *thr) { + ThreadFinish(thr); + internal_free(thr); +} + +void __tsan_acquire(ThreadState *thr, void *addr) { + Acquire(thr, 0, (uptr)addr); +} + +void __tsan_release(ThreadState *thr, void *addr) { + ReleaseStore(thr, 0, (uptr)addr); +} + +void __tsan_release_merge(ThreadState *thr, void *addr) { + Release(thr, 0, (uptr)addr); +} + +void __tsan_finalizer_goroutine(ThreadState *thr) { + AcquireGlobal(thr, 0); +} + +void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) { +} + +void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) { + if (write) + MutexLock(thr, 0, addr); + else + MutexReadLock(thr, 0, addr); +} + +void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) { + if (write) + MutexUnlock(thr, 0, addr); + else + MutexReadUnlock(thr, 0, addr); +} + +void __tsan_go_ignore_sync_begin(ThreadState *thr) { + ThreadIgnoreSyncBegin(thr, 0); +} + +void __tsan_go_ignore_sync_end(ThreadState *thr) { + ThreadIgnoreSyncEnd(thr, 0); +} + +} // extern "C" +} // namespace __tsan + +namespace __sanitizer { + +void SymbolizerPrepareForSandboxing() { + // Nothing to do here for Go. +} + +} // namespace __sanitizer |