tsan_go.cc revision ccaafe66eb47e5cf0432a59df11d4be1bcb3a5b1
1//===-- tsan_go.cc --------------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// ThreadSanitizer runtime for Go language. 11// 12//===----------------------------------------------------------------------===// 13 14#include "tsan_rtl.h" 15#include "tsan_symbolize.h" 16#include "sanitizer_common/sanitizer_common.h" 17#include <stdlib.h> 18 19namespace __tsan { 20 21void InitializeInterceptors() { 22} 23 24void InitializeDynamicAnnotations() { 25} 26 27bool IsExpectedReport(uptr addr, uptr size) { 28 return false; 29} 30 31void internal_start_thread(void(*func)(void*), void *arg) { 32} 33 34ReportLocation *SymbolizeData(uptr addr) { 35 return 0; 36} 37 38ReportStack *NewReportStackEntry(uptr addr) { 39 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, 40 sizeof(ReportStack)); 41 internal_memset(ent, 0, sizeof(*ent)); 42 ent->pc = addr; 43 return ent; 44} 45 46void *internal_alloc(MBlockType typ, uptr sz) { 47 return InternalAlloc(sz); 48} 49 50void internal_free(void *p) { 51 InternalFree(p); 52} 53 54// Callback into Go. 55extern "C" int __tsan_symbolize(uptr pc, char **func, char **file, 56 int *line, int *off); 57 58ReportStack *SymbolizeCode(uptr addr) { 59 ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack, 60 sizeof(ReportStack)); 61 internal_memset(s, 0, sizeof(*s)); 62 s->pc = addr; 63 char *func = 0, *file = 0; 64 int line = 0, off = 0; 65 if (__tsan_symbolize(addr, &func, &file, &line, &off)) { 66 s->offset = off; 67 s->func = internal_strdup(func ? func : "??"); 68 s->file = internal_strdup(file ? file : "-"); 69 s->line = line; 70 s->col = 0; 71 free(func); 72 free(file); 73 } 74 return s; 75} 76 77extern "C" { 78 79static ThreadState *main_thr; 80 81static ThreadState *AllocGoroutine() { 82 ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, 83 sizeof(ThreadState)); 84 internal_memset(thr, 0, sizeof(*thr)); 85 return thr; 86} 87 88void __tsan_init(ThreadState **thrp) { 89 ThreadState *thr = AllocGoroutine(); 90 main_thr = *thrp = thr; 91 thr->in_rtl++; 92 Initialize(thr); 93 thr->in_rtl--; 94} 95 96void __tsan_fini() { 97 // FIXME: Not necessary thread 0. 98 ThreadState *thr = main_thr; 99 thr->in_rtl++; 100 int res = Finalize(thr); 101 thr->in_rtl--; 102 exit(res); 103} 104 105void __tsan_map_shadow(uptr addr, uptr size) { 106 MapShadow(addr, size); 107} 108 109void __tsan_read(ThreadState *thr, void *addr, void *pc) { 110 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 111} 112 113void __tsan_write(ThreadState *thr, void *addr, void *pc) { 114 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 115} 116 117void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr step, 118 void *pc) { 119 (void)step; 120 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false); 121} 122 123void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr step, 124 void *pc) { 125 (void)step; 126 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); 127} 128 129void __tsan_func_enter(ThreadState *thr, void *pc) { 130 FuncEntry(thr, (uptr)pc); 131} 132 133void __tsan_func_exit(ThreadState *thr) { 134 FuncExit(thr); 135} 136 137void __tsan_malloc(ThreadState *thr, void *p, uptr sz, void *pc) { 138 if (thr == 0) // probably before __tsan_init() 139 return; 140 thr->in_rtl++; 141 MemoryResetRange(thr, (uptr)pc, (uptr)p, sz); 142 thr->in_rtl--; 143} 144 145void __tsan_free(void *p) { 146 (void)p; 147} 148 149void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { 150 ThreadState *thr = AllocGoroutine(); 151 *pthr = thr; 152 thr->in_rtl++; 153 parent->in_rtl++; 154 int goid = ThreadCreate(parent, (uptr)pc, 0, true); 155 ThreadStart(thr, goid, 0); 156 parent->in_rtl--; 157 thr->in_rtl--; 158} 159 160void __tsan_go_end(ThreadState *thr) { 161 thr->in_rtl++; 162 ThreadFinish(thr); 163 thr->in_rtl--; 164 internal_free(thr); 165} 166 167void __tsan_acquire(ThreadState *thr, void *addr) { 168 thr->in_rtl++; 169 Acquire(thr, 0, (uptr)addr); 170 thr->in_rtl--; 171} 172 173void __tsan_release(ThreadState *thr, void *addr) { 174 thr->in_rtl++; 175 ReleaseStore(thr, 0, (uptr)addr); 176 thr->in_rtl--; 177} 178 179void __tsan_release_merge(ThreadState *thr, void *addr) { 180 thr->in_rtl++; 181 Release(thr, 0, (uptr)addr); 182 thr->in_rtl--; 183} 184 185void __tsan_finalizer_goroutine(ThreadState *thr) { 186 AcquireGlobal(thr, 0); 187} 188 189} // extern "C" 190} // namespace __tsan 191 192namespace __sanitizer { 193 194void SymbolizerPrepareForSandboxing() { 195 // Nothing to do here for Go. 196} 197 198} // namespace __sanitizer 199