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 return 0; 33} 34 35void internal_join_thread(void *th) { 36} 37 38ReportLocation *SymbolizeData(uptr addr) { 39 return 0; 40} 41 42ReportStack *NewReportStackEntry(uptr addr) { 43 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, 44 sizeof(ReportStack)); 45 internal_memset(ent, 0, sizeof(*ent)); 46 ent->pc = addr; 47 return ent; 48} 49 50void *internal_alloc(MBlockType typ, uptr sz) { 51 return InternalAlloc(sz); 52} 53 54void internal_free(void *p) { 55 InternalFree(p); 56} 57 58struct SymbolizeContext { 59 uptr pc; 60 char *func; 61 char *file; 62 uptr line; 63 uptr off; 64 uptr res; 65}; 66 67// Callback into Go. 68static void (*symbolize_cb)(SymbolizeContext *ctx); 69 70ReportStack *SymbolizeCode(uptr addr) { 71 ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack, 72 sizeof(ReportStack)); 73 internal_memset(s, 0, sizeof(*s)); 74 s->pc = addr; 75 SymbolizeContext ctx; 76 internal_memset(&ctx, 0, sizeof(ctx)); 77 ctx.pc = addr; 78 symbolize_cb(&ctx); 79 if (ctx.res) { 80 s->offset = ctx.off; 81 s->func = internal_strdup(ctx.func ? ctx.func : "??"); 82 s->file = internal_strdup(ctx.file ? ctx.file : "-"); 83 s->line = ctx.line; 84 s->col = 0; 85 } 86 return s; 87} 88 89extern "C" { 90 91static ThreadState *main_thr; 92static bool inited; 93 94static ThreadState *AllocGoroutine() { 95 ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, 96 sizeof(ThreadState)); 97 internal_memset(thr, 0, sizeof(*thr)); 98 return thr; 99} 100 101void __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) { 102 symbolize_cb = cb; 103 ThreadState *thr = AllocGoroutine(); 104 main_thr = *thrp = thr; 105 Initialize(thr); 106 inited = true; 107} 108 109void __tsan_fini() { 110 // FIXME: Not necessary thread 0. 111 ThreadState *thr = main_thr; 112 int res = Finalize(thr); 113 exit(res); 114} 115 116void __tsan_map_shadow(uptr addr, uptr size) { 117 MapShadow(addr, size); 118} 119 120void __tsan_read(ThreadState *thr, void *addr, void *pc) { 121 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 122} 123 124void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { 125 if (callpc != 0) 126 FuncEntry(thr, callpc); 127 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 128 if (callpc != 0) 129 FuncExit(thr); 130} 131 132void __tsan_write(ThreadState *thr, void *addr, void *pc) { 133 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 134} 135 136void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { 137 if (callpc != 0) 138 FuncEntry(thr, callpc); 139 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 140 if (callpc != 0) 141 FuncExit(thr); 142} 143 144void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 145 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false); 146} 147 148void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 149 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); 150} 151 152void __tsan_func_enter(ThreadState *thr, void *pc) { 153 FuncEntry(thr, (uptr)pc); 154} 155 156void __tsan_func_exit(ThreadState *thr) { 157 FuncExit(thr); 158} 159 160void __tsan_malloc(void *p, uptr sz) { 161 if (!inited) 162 return; 163 MemoryResetRange(0, 0, (uptr)p, sz); 164} 165 166void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { 167 ThreadState *thr = AllocGoroutine(); 168 *pthr = thr; 169 int goid = ThreadCreate(parent, (uptr)pc, 0, true); 170 ThreadStart(thr, goid, 0); 171} 172 173void __tsan_go_end(ThreadState *thr) { 174 ThreadFinish(thr); 175 internal_free(thr); 176} 177 178void __tsan_acquire(ThreadState *thr, void *addr) { 179 Acquire(thr, 0, (uptr)addr); 180} 181 182void __tsan_release(ThreadState *thr, void *addr) { 183 ReleaseStore(thr, 0, (uptr)addr); 184} 185 186void __tsan_release_merge(ThreadState *thr, void *addr) { 187 Release(thr, 0, (uptr)addr); 188} 189 190void __tsan_finalizer_goroutine(ThreadState *thr) { 191 AcquireGlobal(thr, 0); 192} 193 194void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) { 195} 196 197void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) { 198 if (write) 199 MutexLock(thr, 0, addr); 200 else 201 MutexReadLock(thr, 0, addr); 202} 203 204void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) { 205 if (write) 206 MutexUnlock(thr, 0, addr); 207 else 208 MutexReadUnlock(thr, 0, addr); 209} 210 211} // extern "C" 212} // namespace __tsan 213 214namespace __sanitizer { 215 216void SymbolizerPrepareForSandboxing() { 217 // Nothing to do here for Go. 218} 219 220} // namespace __sanitizer 221