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 19 namespace __tsan { 20 21 void InitializeInterceptors() { 22 } 23 24 void InitializeDynamicAnnotations() { 25 } 26 27 bool IsExpectedReport(uptr addr, uptr size) { 28 return false; 29 } 30 31 void *internal_start_thread(void(*func)(void*), void *arg) { 32 return 0; 33 } 34 35 void internal_join_thread(void *th) { 36 } 37 38 ReportLocation *SymbolizeData(uptr addr) { 39 return 0; 40 } 41 42 ReportStack *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 50 void *internal_alloc(MBlockType typ, uptr sz) { 51 return InternalAlloc(sz); 52 } 53 54 void internal_free(void *p) { 55 InternalFree(p); 56 } 57 58 struct 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. 68 static void (*symbolize_cb)(SymbolizeContext *ctx); 69 70 ReportStack *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 89 extern "C" { 90 91 static ThreadState *main_thr; 92 static bool inited; 93 94 static ThreadState *AllocGoroutine() { 95 ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, 96 sizeof(ThreadState)); 97 internal_memset(thr, 0, sizeof(*thr)); 98 return thr; 99 } 100 101 void __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 109 void __tsan_fini() { 110 // FIXME: Not necessary thread 0. 111 ThreadState *thr = main_thr; 112 int res = Finalize(thr); 113 exit(res); 114 } 115 116 void __tsan_map_shadow(uptr addr, uptr size) { 117 MapShadow(addr, size); 118 } 119 120 void __tsan_read(ThreadState *thr, void *addr, void *pc) { 121 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 122 } 123 124 void __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 132 void __tsan_write(ThreadState *thr, void *addr, void *pc) { 133 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 134 } 135 136 void __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 144 void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 145 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false); 146 } 147 148 void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 149 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); 150 } 151 152 void __tsan_func_enter(ThreadState *thr, void *pc) { 153 FuncEntry(thr, (uptr)pc); 154 } 155 156 void __tsan_func_exit(ThreadState *thr) { 157 FuncExit(thr); 158 } 159 160 void __tsan_malloc(void *p, uptr sz) { 161 if (!inited) 162 return; 163 MemoryResetRange(0, 0, (uptr)p, sz); 164 } 165 166 void __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 173 void __tsan_go_end(ThreadState *thr) { 174 ThreadFinish(thr); 175 internal_free(thr); 176 } 177 178 void __tsan_acquire(ThreadState *thr, void *addr) { 179 Acquire(thr, 0, (uptr)addr); 180 } 181 182 void __tsan_release(ThreadState *thr, void *addr) { 183 ReleaseStore(thr, 0, (uptr)addr); 184 } 185 186 void __tsan_release_merge(ThreadState *thr, void *addr) { 187 Release(thr, 0, (uptr)addr); 188 } 189 190 void __tsan_finalizer_goroutine(ThreadState *thr) { 191 AcquireGlobal(thr, 0); 192 } 193 194 void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) { 195 } 196 197 void __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 204 void __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 214 namespace __sanitizer { 215 216 void SymbolizerPrepareForSandboxing() { 217 // Nothing to do here for Go. 218 } 219 220 } // namespace __sanitizer 221