1 //===-- tsan_go.cc --------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // ThreadSanitizer runtime for Go language.
12 //===----------------------------------------------------------------------===//
15 #include "tsan_symbolize.h"
16 #include "sanitizer_common/sanitizer_common.h"
21 void InitializeInterceptors() {
24 void InitializeDynamicAnnotations() {
27 bool IsExpectedReport(uptr addr, uptr size) {
31 void *internal_alloc(MBlockType typ, uptr sz) {
32 return InternalAlloc(sz);
35 void internal_free(void *p) {
40 static void (*go_runtime_cb)(uptr cmd, void *ctx);
44 CallbackSymbolizeCode = 1,
45 CallbackSymbolizeData = 2,
48 struct SymbolizeCodeContext {
57 SymbolizedStack *SymbolizeCode(uptr addr) {
58 SymbolizedStack *s = SymbolizedStack::New(addr);
59 SymbolizeCodeContext cbctx;
60 internal_memset(&cbctx, 0, sizeof(cbctx));
62 go_runtime_cb(CallbackSymbolizeCode, &cbctx);
64 AddressInfo &info = s->info;
65 info.module_offset = cbctx.off;
66 info.function = internal_strdup(cbctx.func ? cbctx.func : "??");
67 info.file = internal_strdup(cbctx.file ? cbctx.file : "-");
68 info.line = cbctx.line;
74 struct SymbolizeDataContext {
85 ReportLocation *SymbolizeData(uptr addr) {
86 SymbolizeDataContext cbctx;
87 internal_memset(&cbctx, 0, sizeof(cbctx));
89 go_runtime_cb(CallbackSymbolizeData, &cbctx);
93 MBlock *b = ctx->metamap.GetBlock(cbctx.start);
96 ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
97 loc->heap_chunk_start = cbctx.start;
98 loc->heap_chunk_size = b->siz;
100 loc->stack = SymbolizeStackId(b->stk);
103 ReportLocation *loc = ReportLocation::New(ReportLocationGlobal);
104 loc->global.name = internal_strdup(cbctx.name ? cbctx.name : "??");
105 loc->global.file = internal_strdup(cbctx.file ? cbctx.file : "??");
106 loc->global.line = cbctx.line;
107 loc->global.start = cbctx.start;
108 loc->global.size = cbctx.size;
113 static ThreadState *main_thr;
116 static Processor* get_cur_proc() {
117 if (UNLIKELY(!inited)) {
118 // Running Initialize().
119 // We have not yet returned the Processor to Go, so we cannot ask it back.
120 // Currently, Initialize() does not use the Processor, so return nullptr.
124 go_runtime_cb(CallbackGetProc, &proc);
128 Processor *ThreadState::proc() {
129 return get_cur_proc();
134 static ThreadState *AllocGoroutine() {
135 ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
136 sizeof(ThreadState));
137 internal_memset(thr, 0, sizeof(*thr));
141 void __tsan_init(ThreadState **thrp, Processor **procp,
142 void (*cb)(uptr cmd, void *cb)) {
144 ThreadState *thr = AllocGoroutine();
145 main_thr = *thrp = thr;
152 // FIXME: Not necessary thread 0.
153 ThreadState *thr = main_thr;
154 int res = Finalize(thr);
158 void __tsan_map_shadow(uptr addr, uptr size) {
159 MapShadow(addr, size);
162 void __tsan_read(ThreadState *thr, void *addr, void *pc) {
163 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
166 void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
168 FuncEntry(thr, callpc);
169 MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
174 void __tsan_write(ThreadState *thr, void *addr, void *pc) {
175 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
178 void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
180 FuncEntry(thr, callpc);
181 MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
186 void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
187 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false);
190 void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
191 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true);
194 void __tsan_func_enter(ThreadState *thr, void *pc) {
195 FuncEntry(thr, (uptr)pc);
198 void __tsan_func_exit(ThreadState *thr) {
202 void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) {
205 ctx->metamap.AllocBlock(thr, pc, p, sz);
206 MemoryResetRange(0, 0, (uptr)p, sz);
209 void __tsan_free(uptr p, uptr sz) {
210 ctx->metamap.FreeRange(get_cur_proc(), p, sz);
213 void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
214 ThreadState *thr = AllocGoroutine();
216 int goid = ThreadCreate(parent, (uptr)pc, 0, true);
217 ThreadStart(thr, goid, 0, /*workerthread*/ false);
220 void __tsan_go_end(ThreadState *thr) {
225 void __tsan_proc_create(Processor **pproc) {
226 *pproc = ProcCreate();
229 void __tsan_proc_destroy(Processor *proc) {
233 void __tsan_acquire(ThreadState *thr, void *addr) {
234 Acquire(thr, 0, (uptr)addr);
237 void __tsan_release(ThreadState *thr, void *addr) {
238 ReleaseStore(thr, 0, (uptr)addr);
241 void __tsan_release_merge(ThreadState *thr, void *addr) {
242 Release(thr, 0, (uptr)addr);
245 void __tsan_finalizer_goroutine(ThreadState *thr) {
246 AcquireGlobal(thr, 0);
249 void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) {
251 MutexPreLock(thr, 0, addr);
253 MutexPreReadLock(thr, 0, addr);
256 void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) {
258 MutexPostLock(thr, 0, addr);
260 MutexPostReadLock(thr, 0, addr);
263 void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) {
265 MutexUnlock(thr, 0, addr);
267 MutexReadUnlock(thr, 0, addr);
270 void __tsan_go_ignore_sync_begin(ThreadState *thr) {
271 ThreadIgnoreSyncBegin(thr, 0);
274 void __tsan_go_ignore_sync_end(ThreadState *thr) {
275 ThreadIgnoreSyncEnd(thr, 0);
278 void __tsan_report_count(u64 *pn) {
279 Lock lock(&ctx->report_mtx);
280 *pn = ctx->nreported;
284 } // namespace __tsan
286 namespace __sanitizer {
288 void SymbolizerPrepareForSandboxing() {
289 // Nothing to do here for Go.
292 } // namespace __sanitizer