summaryrefslogtreecommitdiffstats
path: root/contrib/compiler-rt/lib/tsan/go
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/compiler-rt/lib/tsan/go')
-rw-r--r--contrib/compiler-rt/lib/tsan/go/build.bat4
-rwxr-xr-xcontrib/compiler-rt/lib/tsan/go/buildgo.sh103
-rw-r--r--contrib/compiler-rt/lib/tsan/go/test.c65
-rw-r--r--contrib/compiler-rt/lib/tsan/go/tsan_go.cc218
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
OpenPOWER on IntegriCloud