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