]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
1a4d82fc JJ |
31 | ReportLocation *SymbolizeData(uptr addr) { |
32 | return 0; | |
33 | } | |
34 | ||
1a4d82fc JJ |
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 | ||
92a42be0 SL |
55 | SymbolizedStack *SymbolizeCode(uptr addr) { |
56 | SymbolizedStack *s = SymbolizedStack::New(addr); | |
1a4d82fc JJ |
57 | SymbolizeContext ctx; |
58 | internal_memset(&ctx, 0, sizeof(ctx)); | |
59 | ctx.pc = addr; | |
60 | symbolize_cb(&ctx); | |
61 | if (ctx.res) { | |
92a42be0 SL |
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; | |
1a4d82fc JJ |
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 | ||
92a42be0 | 177 | void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) { |
1a4d82fc JJ |
178 | } |
179 | ||
92a42be0 | 180 | void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) { |
1a4d82fc JJ |
181 | if (write) |
182 | MutexLock(thr, 0, addr); | |
183 | else | |
184 | MutexReadLock(thr, 0, addr); | |
185 | } | |
186 | ||
92a42be0 | 187 | void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) { |
1a4d82fc JJ |
188 | if (write) |
189 | MutexUnlock(thr, 0, addr); | |
190 | else | |
191 | MutexReadUnlock(thr, 0, addr); | |
192 | } | |
193 | ||
92a42be0 SL |
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 | ||
1a4d82fc JJ |
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 |