1*7c3d14c8STreehugger Robot //===-- tsan_go.cc --------------------------------------------------------===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // ThreadSanitizer runtime for Go language.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
13*7c3d14c8STreehugger Robot
14*7c3d14c8STreehugger Robot #include "tsan_rtl.h"
15*7c3d14c8STreehugger Robot #include "tsan_symbolize.h"
16*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
17*7c3d14c8STreehugger Robot #include <stdlib.h>
18*7c3d14c8STreehugger Robot
19*7c3d14c8STreehugger Robot namespace __tsan {
20*7c3d14c8STreehugger Robot
InitializeInterceptors()21*7c3d14c8STreehugger Robot void InitializeInterceptors() {
22*7c3d14c8STreehugger Robot }
23*7c3d14c8STreehugger Robot
InitializeDynamicAnnotations()24*7c3d14c8STreehugger Robot void InitializeDynamicAnnotations() {
25*7c3d14c8STreehugger Robot }
26*7c3d14c8STreehugger Robot
IsExpectedReport(uptr addr,uptr size)27*7c3d14c8STreehugger Robot bool IsExpectedReport(uptr addr, uptr size) {
28*7c3d14c8STreehugger Robot return false;
29*7c3d14c8STreehugger Robot }
30*7c3d14c8STreehugger Robot
internal_alloc(MBlockType typ,uptr sz)31*7c3d14c8STreehugger Robot void *internal_alloc(MBlockType typ, uptr sz) {
32*7c3d14c8STreehugger Robot return InternalAlloc(sz);
33*7c3d14c8STreehugger Robot }
34*7c3d14c8STreehugger Robot
internal_free(void * p)35*7c3d14c8STreehugger Robot void internal_free(void *p) {
36*7c3d14c8STreehugger Robot InternalFree(p);
37*7c3d14c8STreehugger Robot }
38*7c3d14c8STreehugger Robot
39*7c3d14c8STreehugger Robot // Callback into Go.
40*7c3d14c8STreehugger Robot static void (*go_runtime_cb)(uptr cmd, void *ctx);
41*7c3d14c8STreehugger Robot
42*7c3d14c8STreehugger Robot enum {
43*7c3d14c8STreehugger Robot CallbackGetProc = 0,
44*7c3d14c8STreehugger Robot CallbackSymbolizeCode = 1,
45*7c3d14c8STreehugger Robot CallbackSymbolizeData = 2,
46*7c3d14c8STreehugger Robot };
47*7c3d14c8STreehugger Robot
48*7c3d14c8STreehugger Robot struct SymbolizeCodeContext {
49*7c3d14c8STreehugger Robot uptr pc;
50*7c3d14c8STreehugger Robot char *func;
51*7c3d14c8STreehugger Robot char *file;
52*7c3d14c8STreehugger Robot uptr line;
53*7c3d14c8STreehugger Robot uptr off;
54*7c3d14c8STreehugger Robot uptr res;
55*7c3d14c8STreehugger Robot };
56*7c3d14c8STreehugger Robot
SymbolizeCode(uptr addr)57*7c3d14c8STreehugger Robot SymbolizedStack *SymbolizeCode(uptr addr) {
58*7c3d14c8STreehugger Robot SymbolizedStack *s = SymbolizedStack::New(addr);
59*7c3d14c8STreehugger Robot SymbolizeCodeContext cbctx;
60*7c3d14c8STreehugger Robot internal_memset(&cbctx, 0, sizeof(cbctx));
61*7c3d14c8STreehugger Robot cbctx.pc = addr;
62*7c3d14c8STreehugger Robot go_runtime_cb(CallbackSymbolizeCode, &cbctx);
63*7c3d14c8STreehugger Robot if (cbctx.res) {
64*7c3d14c8STreehugger Robot AddressInfo &info = s->info;
65*7c3d14c8STreehugger Robot info.module_offset = cbctx.off;
66*7c3d14c8STreehugger Robot info.function = internal_strdup(cbctx.func ? cbctx.func : "??");
67*7c3d14c8STreehugger Robot info.file = internal_strdup(cbctx.file ? cbctx.file : "-");
68*7c3d14c8STreehugger Robot info.line = cbctx.line;
69*7c3d14c8STreehugger Robot info.column = 0;
70*7c3d14c8STreehugger Robot }
71*7c3d14c8STreehugger Robot return s;
72*7c3d14c8STreehugger Robot }
73*7c3d14c8STreehugger Robot
74*7c3d14c8STreehugger Robot struct SymbolizeDataContext {
75*7c3d14c8STreehugger Robot uptr addr;
76*7c3d14c8STreehugger Robot uptr heap;
77*7c3d14c8STreehugger Robot uptr start;
78*7c3d14c8STreehugger Robot uptr size;
79*7c3d14c8STreehugger Robot char *name;
80*7c3d14c8STreehugger Robot char *file;
81*7c3d14c8STreehugger Robot uptr line;
82*7c3d14c8STreehugger Robot uptr res;
83*7c3d14c8STreehugger Robot };
84*7c3d14c8STreehugger Robot
SymbolizeData(uptr addr)85*7c3d14c8STreehugger Robot ReportLocation *SymbolizeData(uptr addr) {
86*7c3d14c8STreehugger Robot SymbolizeDataContext cbctx;
87*7c3d14c8STreehugger Robot internal_memset(&cbctx, 0, sizeof(cbctx));
88*7c3d14c8STreehugger Robot cbctx.addr = addr;
89*7c3d14c8STreehugger Robot go_runtime_cb(CallbackSymbolizeData, &cbctx);
90*7c3d14c8STreehugger Robot if (!cbctx.res)
91*7c3d14c8STreehugger Robot return 0;
92*7c3d14c8STreehugger Robot if (cbctx.heap) {
93*7c3d14c8STreehugger Robot MBlock *b = ctx->metamap.GetBlock(cbctx.start);
94*7c3d14c8STreehugger Robot if (!b)
95*7c3d14c8STreehugger Robot return 0;
96*7c3d14c8STreehugger Robot ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
97*7c3d14c8STreehugger Robot loc->heap_chunk_start = cbctx.start;
98*7c3d14c8STreehugger Robot loc->heap_chunk_size = b->siz;
99*7c3d14c8STreehugger Robot loc->tid = b->tid;
100*7c3d14c8STreehugger Robot loc->stack = SymbolizeStackId(b->stk);
101*7c3d14c8STreehugger Robot return loc;
102*7c3d14c8STreehugger Robot } else {
103*7c3d14c8STreehugger Robot ReportLocation *loc = ReportLocation::New(ReportLocationGlobal);
104*7c3d14c8STreehugger Robot loc->global.name = internal_strdup(cbctx.name ? cbctx.name : "??");
105*7c3d14c8STreehugger Robot loc->global.file = internal_strdup(cbctx.file ? cbctx.file : "??");
106*7c3d14c8STreehugger Robot loc->global.line = cbctx.line;
107*7c3d14c8STreehugger Robot loc->global.start = cbctx.start;
108*7c3d14c8STreehugger Robot loc->global.size = cbctx.size;
109*7c3d14c8STreehugger Robot return loc;
110*7c3d14c8STreehugger Robot }
111*7c3d14c8STreehugger Robot }
112*7c3d14c8STreehugger Robot
113*7c3d14c8STreehugger Robot static ThreadState *main_thr;
114*7c3d14c8STreehugger Robot static bool inited;
115*7c3d14c8STreehugger Robot
get_cur_proc()116*7c3d14c8STreehugger Robot static Processor* get_cur_proc() {
117*7c3d14c8STreehugger Robot if (UNLIKELY(!inited)) {
118*7c3d14c8STreehugger Robot // Running Initialize().
119*7c3d14c8STreehugger Robot // We have not yet returned the Processor to Go, so we cannot ask it back.
120*7c3d14c8STreehugger Robot // Currently, Initialize() does not use the Processor, so return nullptr.
121*7c3d14c8STreehugger Robot return nullptr;
122*7c3d14c8STreehugger Robot }
123*7c3d14c8STreehugger Robot Processor *proc;
124*7c3d14c8STreehugger Robot go_runtime_cb(CallbackGetProc, &proc);
125*7c3d14c8STreehugger Robot return proc;
126*7c3d14c8STreehugger Robot }
127*7c3d14c8STreehugger Robot
proc()128*7c3d14c8STreehugger Robot Processor *ThreadState::proc() {
129*7c3d14c8STreehugger Robot return get_cur_proc();
130*7c3d14c8STreehugger Robot }
131*7c3d14c8STreehugger Robot
132*7c3d14c8STreehugger Robot extern "C" {
133*7c3d14c8STreehugger Robot
AllocGoroutine()134*7c3d14c8STreehugger Robot static ThreadState *AllocGoroutine() {
135*7c3d14c8STreehugger Robot ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
136*7c3d14c8STreehugger Robot sizeof(ThreadState));
137*7c3d14c8STreehugger Robot internal_memset(thr, 0, sizeof(*thr));
138*7c3d14c8STreehugger Robot return thr;
139*7c3d14c8STreehugger Robot }
140*7c3d14c8STreehugger Robot
__tsan_init(ThreadState ** thrp,Processor ** procp,void (* cb)(uptr cmd,void * cb))141*7c3d14c8STreehugger Robot void __tsan_init(ThreadState **thrp, Processor **procp,
142*7c3d14c8STreehugger Robot void (*cb)(uptr cmd, void *cb)) {
143*7c3d14c8STreehugger Robot go_runtime_cb = cb;
144*7c3d14c8STreehugger Robot ThreadState *thr = AllocGoroutine();
145*7c3d14c8STreehugger Robot main_thr = *thrp = thr;
146*7c3d14c8STreehugger Robot Initialize(thr);
147*7c3d14c8STreehugger Robot *procp = thr->proc1;
148*7c3d14c8STreehugger Robot inited = true;
149*7c3d14c8STreehugger Robot }
150*7c3d14c8STreehugger Robot
__tsan_fini()151*7c3d14c8STreehugger Robot void __tsan_fini() {
152*7c3d14c8STreehugger Robot // FIXME: Not necessary thread 0.
153*7c3d14c8STreehugger Robot ThreadState *thr = main_thr;
154*7c3d14c8STreehugger Robot int res = Finalize(thr);
155*7c3d14c8STreehugger Robot exit(res);
156*7c3d14c8STreehugger Robot }
157*7c3d14c8STreehugger Robot
__tsan_map_shadow(uptr addr,uptr size)158*7c3d14c8STreehugger Robot void __tsan_map_shadow(uptr addr, uptr size) {
159*7c3d14c8STreehugger Robot MapShadow(addr, size);
160*7c3d14c8STreehugger Robot }
161*7c3d14c8STreehugger Robot
__tsan_read(ThreadState * thr,void * addr,void * pc)162*7c3d14c8STreehugger Robot void __tsan_read(ThreadState *thr, void *addr, void *pc) {
163*7c3d14c8STreehugger Robot MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
164*7c3d14c8STreehugger Robot }
165*7c3d14c8STreehugger Robot
__tsan_read_pc(ThreadState * thr,void * addr,uptr callpc,uptr pc)166*7c3d14c8STreehugger Robot void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
167*7c3d14c8STreehugger Robot if (callpc != 0)
168*7c3d14c8STreehugger Robot FuncEntry(thr, callpc);
169*7c3d14c8STreehugger Robot MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
170*7c3d14c8STreehugger Robot if (callpc != 0)
171*7c3d14c8STreehugger Robot FuncExit(thr);
172*7c3d14c8STreehugger Robot }
173*7c3d14c8STreehugger Robot
__tsan_write(ThreadState * thr,void * addr,void * pc)174*7c3d14c8STreehugger Robot void __tsan_write(ThreadState *thr, void *addr, void *pc) {
175*7c3d14c8STreehugger Robot MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
176*7c3d14c8STreehugger Robot }
177*7c3d14c8STreehugger Robot
__tsan_write_pc(ThreadState * thr,void * addr,uptr callpc,uptr pc)178*7c3d14c8STreehugger Robot void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
179*7c3d14c8STreehugger Robot if (callpc != 0)
180*7c3d14c8STreehugger Robot FuncEntry(thr, callpc);
181*7c3d14c8STreehugger Robot MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
182*7c3d14c8STreehugger Robot if (callpc != 0)
183*7c3d14c8STreehugger Robot FuncExit(thr);
184*7c3d14c8STreehugger Robot }
185*7c3d14c8STreehugger Robot
__tsan_read_range(ThreadState * thr,void * addr,uptr size,uptr pc)186*7c3d14c8STreehugger Robot void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
187*7c3d14c8STreehugger Robot MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false);
188*7c3d14c8STreehugger Robot }
189*7c3d14c8STreehugger Robot
__tsan_write_range(ThreadState * thr,void * addr,uptr size,uptr pc)190*7c3d14c8STreehugger Robot void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
191*7c3d14c8STreehugger Robot MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true);
192*7c3d14c8STreehugger Robot }
193*7c3d14c8STreehugger Robot
__tsan_func_enter(ThreadState * thr,void * pc)194*7c3d14c8STreehugger Robot void __tsan_func_enter(ThreadState *thr, void *pc) {
195*7c3d14c8STreehugger Robot FuncEntry(thr, (uptr)pc);
196*7c3d14c8STreehugger Robot }
197*7c3d14c8STreehugger Robot
__tsan_func_exit(ThreadState * thr)198*7c3d14c8STreehugger Robot void __tsan_func_exit(ThreadState *thr) {
199*7c3d14c8STreehugger Robot FuncExit(thr);
200*7c3d14c8STreehugger Robot }
201*7c3d14c8STreehugger Robot
__tsan_malloc(ThreadState * thr,uptr pc,uptr p,uptr sz)202*7c3d14c8STreehugger Robot void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) {
203*7c3d14c8STreehugger Robot CHECK(inited);
204*7c3d14c8STreehugger Robot if (thr && pc)
205*7c3d14c8STreehugger Robot ctx->metamap.AllocBlock(thr, pc, p, sz);
206*7c3d14c8STreehugger Robot MemoryResetRange(0, 0, (uptr)p, sz);
207*7c3d14c8STreehugger Robot }
208*7c3d14c8STreehugger Robot
__tsan_free(uptr p,uptr sz)209*7c3d14c8STreehugger Robot void __tsan_free(uptr p, uptr sz) {
210*7c3d14c8STreehugger Robot ctx->metamap.FreeRange(get_cur_proc(), p, sz);
211*7c3d14c8STreehugger Robot }
212*7c3d14c8STreehugger Robot
__tsan_go_start(ThreadState * parent,ThreadState ** pthr,void * pc)213*7c3d14c8STreehugger Robot void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
214*7c3d14c8STreehugger Robot ThreadState *thr = AllocGoroutine();
215*7c3d14c8STreehugger Robot *pthr = thr;
216*7c3d14c8STreehugger Robot int goid = ThreadCreate(parent, (uptr)pc, 0, true);
217*7c3d14c8STreehugger Robot ThreadStart(thr, goid, 0);
218*7c3d14c8STreehugger Robot }
219*7c3d14c8STreehugger Robot
__tsan_go_end(ThreadState * thr)220*7c3d14c8STreehugger Robot void __tsan_go_end(ThreadState *thr) {
221*7c3d14c8STreehugger Robot ThreadFinish(thr);
222*7c3d14c8STreehugger Robot internal_free(thr);
223*7c3d14c8STreehugger Robot }
224*7c3d14c8STreehugger Robot
__tsan_proc_create(Processor ** pproc)225*7c3d14c8STreehugger Robot void __tsan_proc_create(Processor **pproc) {
226*7c3d14c8STreehugger Robot *pproc = ProcCreate();
227*7c3d14c8STreehugger Robot }
228*7c3d14c8STreehugger Robot
__tsan_proc_destroy(Processor * proc)229*7c3d14c8STreehugger Robot void __tsan_proc_destroy(Processor *proc) {
230*7c3d14c8STreehugger Robot ProcDestroy(proc);
231*7c3d14c8STreehugger Robot }
232*7c3d14c8STreehugger Robot
__tsan_acquire(ThreadState * thr,void * addr)233*7c3d14c8STreehugger Robot void __tsan_acquire(ThreadState *thr, void *addr) {
234*7c3d14c8STreehugger Robot Acquire(thr, 0, (uptr)addr);
235*7c3d14c8STreehugger Robot }
236*7c3d14c8STreehugger Robot
__tsan_release(ThreadState * thr,void * addr)237*7c3d14c8STreehugger Robot void __tsan_release(ThreadState *thr, void *addr) {
238*7c3d14c8STreehugger Robot ReleaseStore(thr, 0, (uptr)addr);
239*7c3d14c8STreehugger Robot }
240*7c3d14c8STreehugger Robot
__tsan_release_merge(ThreadState * thr,void * addr)241*7c3d14c8STreehugger Robot void __tsan_release_merge(ThreadState *thr, void *addr) {
242*7c3d14c8STreehugger Robot Release(thr, 0, (uptr)addr);
243*7c3d14c8STreehugger Robot }
244*7c3d14c8STreehugger Robot
__tsan_finalizer_goroutine(ThreadState * thr)245*7c3d14c8STreehugger Robot void __tsan_finalizer_goroutine(ThreadState *thr) {
246*7c3d14c8STreehugger Robot AcquireGlobal(thr, 0);
247*7c3d14c8STreehugger Robot }
248*7c3d14c8STreehugger Robot
__tsan_mutex_before_lock(ThreadState * thr,uptr addr,uptr write)249*7c3d14c8STreehugger Robot void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) {
250*7c3d14c8STreehugger Robot }
251*7c3d14c8STreehugger Robot
__tsan_mutex_after_lock(ThreadState * thr,uptr addr,uptr write)252*7c3d14c8STreehugger Robot void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) {
253*7c3d14c8STreehugger Robot if (write)
254*7c3d14c8STreehugger Robot MutexLock(thr, 0, addr);
255*7c3d14c8STreehugger Robot else
256*7c3d14c8STreehugger Robot MutexReadLock(thr, 0, addr);
257*7c3d14c8STreehugger Robot }
258*7c3d14c8STreehugger Robot
__tsan_mutex_before_unlock(ThreadState * thr,uptr addr,uptr write)259*7c3d14c8STreehugger Robot void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) {
260*7c3d14c8STreehugger Robot if (write)
261*7c3d14c8STreehugger Robot MutexUnlock(thr, 0, addr);
262*7c3d14c8STreehugger Robot else
263*7c3d14c8STreehugger Robot MutexReadUnlock(thr, 0, addr);
264*7c3d14c8STreehugger Robot }
265*7c3d14c8STreehugger Robot
__tsan_go_ignore_sync_begin(ThreadState * thr)266*7c3d14c8STreehugger Robot void __tsan_go_ignore_sync_begin(ThreadState *thr) {
267*7c3d14c8STreehugger Robot ThreadIgnoreSyncBegin(thr, 0);
268*7c3d14c8STreehugger Robot }
269*7c3d14c8STreehugger Robot
__tsan_go_ignore_sync_end(ThreadState * thr)270*7c3d14c8STreehugger Robot void __tsan_go_ignore_sync_end(ThreadState *thr) {
271*7c3d14c8STreehugger Robot ThreadIgnoreSyncEnd(thr, 0);
272*7c3d14c8STreehugger Robot }
273*7c3d14c8STreehugger Robot
274*7c3d14c8STreehugger Robot } // extern "C"
275*7c3d14c8STreehugger Robot } // namespace __tsan
276*7c3d14c8STreehugger Robot
277*7c3d14c8STreehugger Robot namespace __sanitizer {
278*7c3d14c8STreehugger Robot
SymbolizerPrepareForSandboxing()279*7c3d14c8STreehugger Robot void SymbolizerPrepareForSandboxing() {
280*7c3d14c8STreehugger Robot // Nothing to do here for Go.
281*7c3d14c8STreehugger Robot }
282*7c3d14c8STreehugger Robot
283*7c3d14c8STreehugger Robot } // namespace __sanitizer
284