diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-07 19:55:37 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-07 19:55:37 +0000 |
commit | ca9211ecdede9bdedb812b2243a4abdb8dacd1b9 (patch) | |
tree | 9b19e801150082c33e9152275829a6ce90614b55 /lib/tsan/go | |
parent | 8ef50bf3d1c287b5013c3168de77a462dfce3495 (diff) |
Diffstat (limited to 'lib/tsan/go')
-rw-r--r-- | lib/tsan/go/build.bat | 4 | ||||
-rwxr-xr-x | lib/tsan/go/buildgo.sh | 48 | ||||
-rw-r--r-- | lib/tsan/go/test.c | 20 | ||||
-rw-r--r-- | lib/tsan/go/tsan_go.cc | 138 |
4 files changed, 126 insertions, 84 deletions
diff --git a/lib/tsan/go/build.bat b/lib/tsan/go/build.bat new file mode 100644 index 0000000000000..8f8087fc6352e --- /dev/null +++ b/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/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh index bd03fc0b65e05..4df2e96c5a8c9 100755 --- a/lib/tsan/go/buildgo.sh +++ b/lib/tsan/go/buildgo.sh @@ -1,10 +1,10 @@ -#!/bin/bash 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 @@ -12,43 +12,64 @@ SRCS=" ../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 -Werror" + 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_linux_libcdep.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" + OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option" OSLDFLAGS="-lpthread -fPIC -fpie" SRCS+=" ../rtl/tsan_platform_mac.cc - ../../sanitizer_common/sanitizer_posix.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" + OSCFLAGS="-Wno-error=attributes -Wno-attributes -Wno-unused-const-variable -Wno-unknown-warning-option" OSLDFLAGS="" SRCS+=" ../rtl/tsan_platform_windows.cc @@ -66,18 +87,17 @@ for F in $SRCS; do cat $F >> gotsan.cc done -FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -m64 -Wall -fno-exceptions -fno-rtti -DTSAN_GO -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 $OSCFLAGS" +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 -fomit-frame-pointer" + FLAGS+=" -DTSAN_DEBUG=0 -O3 -msse3 -fomit-frame-pointer" else FLAGS+=" -DTSAN_DEBUG=1 -g" fi -echo gcc gotsan.cc -S -o tmp.s $FLAGS $CFLAGS -gcc gotsan.cc -S -o tmp.s $FLAGS $CFLAGS -cat tmp.s $ASMS > gotsan.s -echo as gotsan.s -o race_$SUFFIX.syso -as gotsan.s -o race_$SUFFIX.syso +CC=${CC:-gcc} + +echo $CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS +$CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS -gcc test.c race_$SUFFIX.syso -m64 -o test $OSLDFLAGS +$CC test.c race_$SUFFIX.syso -m64 -o test $OSLDFLAGS GORACE="exitcode=0 atexit_sleep_ms=0" ./test diff --git a/lib/tsan/go/test.c b/lib/tsan/go/test.c index 859b35d348e89..94433f1b8c221 100644 --- a/lib/tsan/go/test.c +++ b/lib/tsan/go/test.c @@ -13,7 +13,7 @@ #include <stdio.h> -void __tsan_init(void **thr); +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); @@ -22,27 +22,26 @@ 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 *thr, void *p, unsigned long sz, void *pc); -void __tsan_free(void *p); +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); -int __tsan_symbolize(void *pc, char **img, char **rtn, char **file, int *l) { - return 0; -} +void symbolize_cb(void *ctx) {} -char buf[10]; +char buf0[100<<10]; void foobar() {} void barfoo() {} int main(void) { void *thr0 = 0; - __tsan_init(&thr0); - __tsan_map_shadow(buf, sizeof(buf) + 4096); + 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(thr0, buf, 10, 0); + __tsan_malloc(buf, 10); __tsan_release(thr0, buf); __tsan_release_merge(thr0, buf); void *thr1 = 0; @@ -60,7 +59,6 @@ int main(void) { __tsan_read(thr2, buf, (char*)&barfoo + 1); __tsan_func_exit(thr2); __tsan_go_end(thr2); - __tsan_free(buf); __tsan_func_exit(thr0); __tsan_fini(); return 0; diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc index df54bb8e216cd..cccf72cedd27e 100644 --- a/lib/tsan/go/tsan_go.cc +++ b/lib/tsan/go/tsan_go.cc @@ -28,19 +28,15 @@ bool IsExpectedReport(uptr addr, uptr size) { return false; } -void internal_start_thread(void(*func)(void*), void *arg) { +void *internal_start_thread(void(*func)(void*), void *arg) { + return 0; } -ReportLocation *SymbolizeData(uptr addr) { - return 0; +void internal_join_thread(void *th) { } -ReportStack *NewReportStackEntry(uptr addr) { - ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, - sizeof(ReportStack)); - internal_memset(ent, 0, sizeof(*ent)); - ent->pc = addr; - return ent; +ReportLocation *SymbolizeData(uptr addr) { + return 0; } void *internal_alloc(MBlockType typ, uptr sz) { @@ -51,25 +47,31 @@ void internal_free(void *p) { InternalFree(p); } +struct SymbolizeContext { + uptr pc; + char *func; + char *file; + uptr line; + uptr off; + uptr res; +}; + // Callback into Go. -extern "C" int __tsan_symbolize(uptr pc, char **func, char **file, - int *line, int *off); - -ReportStack *SymbolizeCode(uptr addr) { - ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack, - sizeof(ReportStack)); - internal_memset(s, 0, sizeof(*s)); - s->pc = addr; - char *func = 0, *file = 0; - int line = 0, off = 0; - if (__tsan_symbolize(addr, &func, &file, &line, &off)) { - s->offset = off; - s->func = internal_strdup(func ? func : "??"); - s->file = internal_strdup(file ? file : "-"); - s->line = line; - s->col = 0; - free(func); - free(file); +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; } @@ -77,6 +79,7 @@ ReportStack *SymbolizeCode(uptr addr) { extern "C" { static ThreadState *main_thr; +static bool inited; static ThreadState *AllocGoroutine() { ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, @@ -85,20 +88,18 @@ static ThreadState *AllocGoroutine() { return thr; } -void __tsan_init(ThreadState **thrp) { +void __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) { + symbolize_cb = cb; ThreadState *thr = AllocGoroutine(); main_thr = *thrp = thr; - thr->in_rtl++; Initialize(thr); - thr->in_rtl--; + inited = true; } void __tsan_fini() { // FIXME: Not necessary thread 0. ThreadState *thr = main_thr; - thr->in_rtl++; int res = Finalize(thr); - thr->in_rtl--; exit(res); } @@ -110,19 +111,31 @@ 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_read_range(ThreadState *thr, void *addr, uptr size, uptr step, - void *pc) { - (void)step; +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 step, - void *pc) { - (void)step; +void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) { MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); } @@ -134,58 +147,65 @@ void __tsan_func_exit(ThreadState *thr) { FuncExit(thr); } -void __tsan_malloc(ThreadState *thr, void *p, uptr sz, void *pc) { - if (thr == 0) // probably before __tsan_init() +void __tsan_malloc(void *p, uptr sz) { + if (!inited) return; - thr->in_rtl++; - MemoryResetRange(thr, (uptr)pc, (uptr)p, sz); - thr->in_rtl--; -} - -void __tsan_free(void *p) { - (void)p; + MemoryResetRange(0, 0, (uptr)p, sz); } void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { ThreadState *thr = AllocGoroutine(); *pthr = thr; - thr->in_rtl++; - parent->in_rtl++; int goid = ThreadCreate(parent, (uptr)pc, 0, true); ThreadStart(thr, goid, 0); - parent->in_rtl--; - thr->in_rtl--; } void __tsan_go_end(ThreadState *thr) { - thr->in_rtl++; ThreadFinish(thr); - thr->in_rtl--; internal_free(thr); } void __tsan_acquire(ThreadState *thr, void *addr) { - thr->in_rtl++; Acquire(thr, 0, (uptr)addr); - thr->in_rtl--; } void __tsan_release(ThreadState *thr, void *addr) { - thr->in_rtl++; ReleaseStore(thr, 0, (uptr)addr); - thr->in_rtl--; } void __tsan_release_merge(ThreadState *thr, void *addr) { - thr->in_rtl++; Release(thr, 0, (uptr)addr); - thr->in_rtl--; } 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 |