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