1 //===-- tsan_interface_java.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 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "tsan_interface_java.h"
15 #include "tsan_rtl.h"
16 #include "tsan_mutex.h"
17 #include "sanitizer_common/sanitizer_internal_defs.h"
18 #include "sanitizer_common/sanitizer_common.h"
19 #include "sanitizer_common/sanitizer_placement_new.h"
20 #include "sanitizer_common/sanitizer_stacktrace.h"
21 #include "sanitizer_common/sanitizer_procmaps.h"
22 
23 using namespace __tsan;  // NOLINT
24 
25 const jptr kHeapAlignment = 8;
26 
27 namespace __tsan {
28 
29 struct JavaContext {
30   const uptr heap_begin;
31   const uptr heap_size;
32 
JavaContext__tsan::JavaContext33   JavaContext(jptr heap_begin, jptr heap_size)
34       : heap_begin(heap_begin)
35       , heap_size(heap_size) {
36   }
37 };
38 
39 class ScopedJavaFunc {
40  public:
ScopedJavaFunc(ThreadState * thr,uptr pc)41   ScopedJavaFunc(ThreadState *thr, uptr pc)
42       : thr_(thr) {
43     Initialize(thr_);
44     FuncEntry(thr, pc);
45   }
46 
~ScopedJavaFunc()47   ~ScopedJavaFunc() {
48     FuncExit(thr_);
49     // FIXME(dvyukov): process pending signals.
50   }
51 
52  private:
53   ThreadState *thr_;
54 };
55 
56 static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
57 static JavaContext *jctx;
58 
59 }  // namespace __tsan
60 
61 #define SCOPED_JAVA_FUNC(func) \
62   ThreadState *thr = cur_thread(); \
63   const uptr caller_pc = GET_CALLER_PC(); \
64   const uptr pc = StackTrace::GetCurrentPc(); \
65   (void)pc; \
66   ScopedJavaFunc scoped(thr, caller_pc); \
67 /**/
68 
__tsan_java_init(jptr heap_begin,jptr heap_size)69 void __tsan_java_init(jptr heap_begin, jptr heap_size) {
70   SCOPED_JAVA_FUNC(__tsan_java_init);
71   DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
72   CHECK_EQ(jctx, 0);
73   CHECK_GT(heap_begin, 0);
74   CHECK_GT(heap_size, 0);
75   CHECK_EQ(heap_begin % kHeapAlignment, 0);
76   CHECK_EQ(heap_size % kHeapAlignment, 0);
77   CHECK_LT(heap_begin, heap_begin + heap_size);
78   jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
79 }
80 
__tsan_java_fini()81 int  __tsan_java_fini() {
82   SCOPED_JAVA_FUNC(__tsan_java_fini);
83   DPrintf("#%d: java_fini()\n", thr->tid);
84   CHECK_NE(jctx, 0);
85   // FIXME(dvyukov): this does not call atexit() callbacks.
86   int status = Finalize(thr);
87   DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
88   return status;
89 }
90 
__tsan_java_alloc(jptr ptr,jptr size)91 void __tsan_java_alloc(jptr ptr, jptr size) {
92   SCOPED_JAVA_FUNC(__tsan_java_alloc);
93   DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
94   CHECK_NE(jctx, 0);
95   CHECK_NE(size, 0);
96   CHECK_EQ(ptr % kHeapAlignment, 0);
97   CHECK_EQ(size % kHeapAlignment, 0);
98   CHECK_GE(ptr, jctx->heap_begin);
99   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
100 
101   OnUserAlloc(thr, pc, ptr, size, false);
102 }
103 
__tsan_java_free(jptr ptr,jptr size)104 void __tsan_java_free(jptr ptr, jptr size) {
105   SCOPED_JAVA_FUNC(__tsan_java_free);
106   DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
107   CHECK_NE(jctx, 0);
108   CHECK_NE(size, 0);
109   CHECK_EQ(ptr % kHeapAlignment, 0);
110   CHECK_EQ(size % kHeapAlignment, 0);
111   CHECK_GE(ptr, jctx->heap_begin);
112   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
113 
114   ctx->metamap.FreeRange(thr, pc, ptr, size);
115 }
116 
__tsan_java_move(jptr src,jptr dst,jptr size)117 void __tsan_java_move(jptr src, jptr dst, jptr size) {
118   SCOPED_JAVA_FUNC(__tsan_java_move);
119   DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
120   CHECK_NE(jctx, 0);
121   CHECK_NE(size, 0);
122   CHECK_EQ(src % kHeapAlignment, 0);
123   CHECK_EQ(dst % kHeapAlignment, 0);
124   CHECK_EQ(size % kHeapAlignment, 0);
125   CHECK_GE(src, jctx->heap_begin);
126   CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
127   CHECK_GE(dst, jctx->heap_begin);
128   CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
129   CHECK_NE(dst, src);
130   CHECK_NE(size, 0);
131 
132   // Assuming it's not running concurrently with threads that do
133   // memory accesses and mutex operations (stop-the-world phase).
134   ctx->metamap.MoveMemory(src, dst, size);
135 
136   // Move shadow.
137   u64 *s = (u64*)MemToShadow(src);
138   u64 *d = (u64*)MemToShadow(dst);
139   u64 *send = (u64*)MemToShadow(src + size);
140   uptr inc = 1;
141   if (dst > src) {
142     s = (u64*)MemToShadow(src + size) - 1;
143     d = (u64*)MemToShadow(dst + size) - 1;
144     send = (u64*)MemToShadow(src) - 1;
145     inc = -1;
146   }
147   for (; s != send; s += inc, d += inc) {
148     *d = *s;
149     *s = 0;
150   }
151 }
152 
__tsan_java_finalize()153 void __tsan_java_finalize() {
154   SCOPED_JAVA_FUNC(__tsan_java_finalize);
155   DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
156   AcquireGlobal(thr, 0);
157 }
158 
__tsan_java_mutex_lock(jptr addr)159 void __tsan_java_mutex_lock(jptr addr) {
160   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
161   DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
162   CHECK_NE(jctx, 0);
163   CHECK_GE(addr, jctx->heap_begin);
164   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
165 
166   MutexCreate(thr, pc, addr, true, true, true);
167   MutexLock(thr, pc, addr);
168 }
169 
__tsan_java_mutex_unlock(jptr addr)170 void __tsan_java_mutex_unlock(jptr addr) {
171   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
172   DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
173   CHECK_NE(jctx, 0);
174   CHECK_GE(addr, jctx->heap_begin);
175   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
176 
177   MutexUnlock(thr, pc, addr);
178 }
179 
__tsan_java_mutex_read_lock(jptr addr)180 void __tsan_java_mutex_read_lock(jptr addr) {
181   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
182   DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
183   CHECK_NE(jctx, 0);
184   CHECK_GE(addr, jctx->heap_begin);
185   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
186 
187   MutexCreate(thr, pc, addr, true, true, true);
188   MutexReadLock(thr, pc, addr);
189 }
190 
__tsan_java_mutex_read_unlock(jptr addr)191 void __tsan_java_mutex_read_unlock(jptr addr) {
192   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
193   DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
194   CHECK_NE(jctx, 0);
195   CHECK_GE(addr, jctx->heap_begin);
196   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
197 
198   MutexReadUnlock(thr, pc, addr);
199 }
200 
__tsan_java_mutex_lock_rec(jptr addr,int rec)201 void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
202   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
203   DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
204   CHECK_NE(jctx, 0);
205   CHECK_GE(addr, jctx->heap_begin);
206   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
207   CHECK_GT(rec, 0);
208 
209   MutexCreate(thr, pc, addr, true, true, true);
210   MutexLock(thr, pc, addr, rec);
211 }
212 
__tsan_java_mutex_unlock_rec(jptr addr)213 int __tsan_java_mutex_unlock_rec(jptr addr) {
214   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
215   DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
216   CHECK_NE(jctx, 0);
217   CHECK_GE(addr, jctx->heap_begin);
218   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
219 
220   return MutexUnlock(thr, pc, addr, true);
221 }
222 
__tsan_java_acquire(jptr addr)223 void __tsan_java_acquire(jptr addr) {
224   SCOPED_JAVA_FUNC(__tsan_java_acquire);
225   DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
226   CHECK_NE(jctx, 0);
227   CHECK_GE(addr, jctx->heap_begin);
228   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
229 
230   Acquire(thr, caller_pc, addr);
231 }
232 
__tsan_java_release(jptr addr)233 void __tsan_java_release(jptr addr) {
234   SCOPED_JAVA_FUNC(__tsan_java_release);
235   DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
236   CHECK_NE(jctx, 0);
237   CHECK_GE(addr, jctx->heap_begin);
238   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
239 
240   Release(thr, caller_pc, addr);
241 }
242 
__tsan_java_release_store(jptr addr)243 void __tsan_java_release_store(jptr addr) {
244   SCOPED_JAVA_FUNC(__tsan_java_release);
245   DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
246   CHECK_NE(jctx, 0);
247   CHECK_GE(addr, jctx->heap_begin);
248   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
249 
250   ReleaseStore(thr, caller_pc, addr);
251 }
252