1*ff6d591cSmrg //===-- tsan_interface_java.cpp -------------------------------------------===//
2*ff6d591cSmrg //
3*ff6d591cSmrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ff6d591cSmrg // See https://llvm.org/LICENSE.txt for license information.
5*ff6d591cSmrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ff6d591cSmrg //
7*ff6d591cSmrg //===----------------------------------------------------------------------===//
8*ff6d591cSmrg //
9*ff6d591cSmrg // This file is a part of ThreadSanitizer (TSan), a race detector.
10*ff6d591cSmrg //
11*ff6d591cSmrg //===----------------------------------------------------------------------===//
12*ff6d591cSmrg
13*ff6d591cSmrg #include "tsan_interface_java.h"
14*ff6d591cSmrg #include "tsan_rtl.h"
15*ff6d591cSmrg #include "sanitizer_common/sanitizer_internal_defs.h"
16*ff6d591cSmrg #include "sanitizer_common/sanitizer_common.h"
17*ff6d591cSmrg #include "sanitizer_common/sanitizer_placement_new.h"
18*ff6d591cSmrg #include "sanitizer_common/sanitizer_stacktrace.h"
19*ff6d591cSmrg #include "sanitizer_common/sanitizer_procmaps.h"
20*ff6d591cSmrg
21*ff6d591cSmrg using namespace __tsan;
22*ff6d591cSmrg
23*ff6d591cSmrg const jptr kHeapAlignment = 8;
24*ff6d591cSmrg
25*ff6d591cSmrg namespace __tsan {
26*ff6d591cSmrg
27*ff6d591cSmrg struct JavaContext {
28*ff6d591cSmrg const uptr heap_begin;
29*ff6d591cSmrg const uptr heap_size;
30*ff6d591cSmrg
JavaContext__tsan::JavaContext31*ff6d591cSmrg JavaContext(jptr heap_begin, jptr heap_size)
32*ff6d591cSmrg : heap_begin(heap_begin)
33*ff6d591cSmrg , heap_size(heap_size) {
34*ff6d591cSmrg }
35*ff6d591cSmrg };
36*ff6d591cSmrg
37*ff6d591cSmrg static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
38*ff6d591cSmrg static JavaContext *jctx;
39*ff6d591cSmrg
JavaHeapBlock(uptr addr,uptr * start)40*ff6d591cSmrg MBlock *JavaHeapBlock(uptr addr, uptr *start) {
41*ff6d591cSmrg if (!jctx || addr < jctx->heap_begin ||
42*ff6d591cSmrg addr >= jctx->heap_begin + jctx->heap_size)
43*ff6d591cSmrg return nullptr;
44*ff6d591cSmrg for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
45*ff6d591cSmrg p -= kMetaShadowCell) {
46*ff6d591cSmrg MBlock *b = ctx->metamap.GetBlock(p);
47*ff6d591cSmrg if (!b)
48*ff6d591cSmrg continue;
49*ff6d591cSmrg if (p + b->siz <= addr)
50*ff6d591cSmrg return nullptr;
51*ff6d591cSmrg *start = p;
52*ff6d591cSmrg return b;
53*ff6d591cSmrg }
54*ff6d591cSmrg return nullptr;
55*ff6d591cSmrg }
56*ff6d591cSmrg
57*ff6d591cSmrg } // namespace __tsan
58*ff6d591cSmrg
59*ff6d591cSmrg #define JAVA_FUNC_ENTER(func) \
60*ff6d591cSmrg ThreadState *thr = cur_thread(); \
61*ff6d591cSmrg (void)thr;
62*ff6d591cSmrg
__tsan_java_init(jptr heap_begin,jptr heap_size)63*ff6d591cSmrg void __tsan_java_init(jptr heap_begin, jptr heap_size) {
64*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_init);
65*ff6d591cSmrg Initialize(thr);
66*ff6d591cSmrg DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
67*ff6d591cSmrg DCHECK_EQ(jctx, 0);
68*ff6d591cSmrg DCHECK_GT(heap_begin, 0);
69*ff6d591cSmrg DCHECK_GT(heap_size, 0);
70*ff6d591cSmrg DCHECK_EQ(heap_begin % kHeapAlignment, 0);
71*ff6d591cSmrg DCHECK_EQ(heap_size % kHeapAlignment, 0);
72*ff6d591cSmrg DCHECK_LT(heap_begin, heap_begin + heap_size);
73*ff6d591cSmrg jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
74*ff6d591cSmrg }
75*ff6d591cSmrg
__tsan_java_fini()76*ff6d591cSmrg int __tsan_java_fini() {
77*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_fini);
78*ff6d591cSmrg DPrintf("#%d: java_fini()\n", thr->tid);
79*ff6d591cSmrg DCHECK_NE(jctx, 0);
80*ff6d591cSmrg // FIXME(dvyukov): this does not call atexit() callbacks.
81*ff6d591cSmrg int status = Finalize(thr);
82*ff6d591cSmrg DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
83*ff6d591cSmrg return status;
84*ff6d591cSmrg }
85*ff6d591cSmrg
__tsan_java_alloc(jptr ptr,jptr size)86*ff6d591cSmrg void __tsan_java_alloc(jptr ptr, jptr size) {
87*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_alloc);
88*ff6d591cSmrg DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
89*ff6d591cSmrg DCHECK_NE(jctx, 0);
90*ff6d591cSmrg DCHECK_NE(size, 0);
91*ff6d591cSmrg DCHECK_EQ(ptr % kHeapAlignment, 0);
92*ff6d591cSmrg DCHECK_EQ(size % kHeapAlignment, 0);
93*ff6d591cSmrg DCHECK_GE(ptr, jctx->heap_begin);
94*ff6d591cSmrg DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
95*ff6d591cSmrg
96*ff6d591cSmrg OnUserAlloc(thr, 0, ptr, size, false);
97*ff6d591cSmrg }
98*ff6d591cSmrg
__tsan_java_free(jptr ptr,jptr size)99*ff6d591cSmrg void __tsan_java_free(jptr ptr, jptr size) {
100*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_free);
101*ff6d591cSmrg DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
102*ff6d591cSmrg DCHECK_NE(jctx, 0);
103*ff6d591cSmrg DCHECK_NE(size, 0);
104*ff6d591cSmrg DCHECK_EQ(ptr % kHeapAlignment, 0);
105*ff6d591cSmrg DCHECK_EQ(size % kHeapAlignment, 0);
106*ff6d591cSmrg DCHECK_GE(ptr, jctx->heap_begin);
107*ff6d591cSmrg DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
108*ff6d591cSmrg
109*ff6d591cSmrg ctx->metamap.FreeRange(thr->proc(), ptr, size);
110*ff6d591cSmrg }
111*ff6d591cSmrg
__tsan_java_move(jptr src,jptr dst,jptr size)112*ff6d591cSmrg void __tsan_java_move(jptr src, jptr dst, jptr size) {
113*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_move);
114*ff6d591cSmrg DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
115*ff6d591cSmrg DCHECK_NE(jctx, 0);
116*ff6d591cSmrg DCHECK_NE(size, 0);
117*ff6d591cSmrg DCHECK_EQ(src % kHeapAlignment, 0);
118*ff6d591cSmrg DCHECK_EQ(dst % kHeapAlignment, 0);
119*ff6d591cSmrg DCHECK_EQ(size % kHeapAlignment, 0);
120*ff6d591cSmrg DCHECK_GE(src, jctx->heap_begin);
121*ff6d591cSmrg DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
122*ff6d591cSmrg DCHECK_GE(dst, jctx->heap_begin);
123*ff6d591cSmrg DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
124*ff6d591cSmrg DCHECK_NE(dst, src);
125*ff6d591cSmrg DCHECK_NE(size, 0);
126*ff6d591cSmrg
127*ff6d591cSmrg // Assuming it's not running concurrently with threads that do
128*ff6d591cSmrg // memory accesses and mutex operations (stop-the-world phase).
129*ff6d591cSmrg ctx->metamap.MoveMemory(src, dst, size);
130*ff6d591cSmrg
131*ff6d591cSmrg // Clear the destination shadow range.
132*ff6d591cSmrg // We used to move shadow from src to dst, but the trace format does not
133*ff6d591cSmrg // support that anymore as it contains addresses of accesses.
134*ff6d591cSmrg RawShadow *d = MemToShadow(dst);
135*ff6d591cSmrg RawShadow *dend = MemToShadow(dst + size);
136*ff6d591cSmrg internal_memset(d, 0, (dend - d) * sizeof(*d));
137*ff6d591cSmrg }
138*ff6d591cSmrg
__tsan_java_find(jptr * from_ptr,jptr to)139*ff6d591cSmrg jptr __tsan_java_find(jptr *from_ptr, jptr to) {
140*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_find);
141*ff6d591cSmrg DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
142*ff6d591cSmrg DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
143*ff6d591cSmrg DCHECK_EQ(to % kHeapAlignment, 0);
144*ff6d591cSmrg DCHECK_GE(*from_ptr, jctx->heap_begin);
145*ff6d591cSmrg DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
146*ff6d591cSmrg for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
147*ff6d591cSmrg MBlock *b = ctx->metamap.GetBlock(from);
148*ff6d591cSmrg if (b) {
149*ff6d591cSmrg *from_ptr = from;
150*ff6d591cSmrg return b->siz;
151*ff6d591cSmrg }
152*ff6d591cSmrg }
153*ff6d591cSmrg return 0;
154*ff6d591cSmrg }
155*ff6d591cSmrg
__tsan_java_finalize()156*ff6d591cSmrg void __tsan_java_finalize() {
157*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_finalize);
158*ff6d591cSmrg DPrintf("#%d: java_finalize()\n", thr->tid);
159*ff6d591cSmrg AcquireGlobal(thr);
160*ff6d591cSmrg }
161*ff6d591cSmrg
__tsan_java_mutex_lock(jptr addr)162*ff6d591cSmrg void __tsan_java_mutex_lock(jptr addr) {
163*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
164*ff6d591cSmrg DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
165*ff6d591cSmrg DCHECK_NE(jctx, 0);
166*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
167*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
168*ff6d591cSmrg
169*ff6d591cSmrg MutexPostLock(thr, 0, addr,
170*ff6d591cSmrg MutexFlagLinkerInit | MutexFlagWriteReentrant |
171*ff6d591cSmrg MutexFlagDoPreLockOnPostLock);
172*ff6d591cSmrg }
173*ff6d591cSmrg
__tsan_java_mutex_unlock(jptr addr)174*ff6d591cSmrg void __tsan_java_mutex_unlock(jptr addr) {
175*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
176*ff6d591cSmrg DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
177*ff6d591cSmrg DCHECK_NE(jctx, 0);
178*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
179*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
180*ff6d591cSmrg
181*ff6d591cSmrg MutexUnlock(thr, 0, addr);
182*ff6d591cSmrg }
183*ff6d591cSmrg
__tsan_java_mutex_read_lock(jptr addr)184*ff6d591cSmrg void __tsan_java_mutex_read_lock(jptr addr) {
185*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
186*ff6d591cSmrg DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
187*ff6d591cSmrg DCHECK_NE(jctx, 0);
188*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
189*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
190*ff6d591cSmrg
191*ff6d591cSmrg MutexPostReadLock(thr, 0, addr,
192*ff6d591cSmrg MutexFlagLinkerInit | MutexFlagWriteReentrant |
193*ff6d591cSmrg MutexFlagDoPreLockOnPostLock);
194*ff6d591cSmrg }
195*ff6d591cSmrg
__tsan_java_mutex_read_unlock(jptr addr)196*ff6d591cSmrg void __tsan_java_mutex_read_unlock(jptr addr) {
197*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
198*ff6d591cSmrg DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
199*ff6d591cSmrg DCHECK_NE(jctx, 0);
200*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
201*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
202*ff6d591cSmrg
203*ff6d591cSmrg MutexReadUnlock(thr, 0, addr);
204*ff6d591cSmrg }
205*ff6d591cSmrg
__tsan_java_mutex_lock_rec(jptr addr,int rec)206*ff6d591cSmrg void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
207*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
208*ff6d591cSmrg DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
209*ff6d591cSmrg DCHECK_NE(jctx, 0);
210*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
211*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212*ff6d591cSmrg DCHECK_GT(rec, 0);
213*ff6d591cSmrg
214*ff6d591cSmrg MutexPostLock(thr, 0, addr,
215*ff6d591cSmrg MutexFlagLinkerInit | MutexFlagWriteReentrant |
216*ff6d591cSmrg MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
217*ff6d591cSmrg rec);
218*ff6d591cSmrg }
219*ff6d591cSmrg
__tsan_java_mutex_unlock_rec(jptr addr)220*ff6d591cSmrg int __tsan_java_mutex_unlock_rec(jptr addr) {
221*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
222*ff6d591cSmrg DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
223*ff6d591cSmrg DCHECK_NE(jctx, 0);
224*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
225*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
226*ff6d591cSmrg
227*ff6d591cSmrg return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
228*ff6d591cSmrg }
229*ff6d591cSmrg
__tsan_java_acquire(jptr addr)230*ff6d591cSmrg void __tsan_java_acquire(jptr addr) {
231*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_acquire);
232*ff6d591cSmrg DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
233*ff6d591cSmrg DCHECK_NE(jctx, 0);
234*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
235*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
236*ff6d591cSmrg
237*ff6d591cSmrg Acquire(thr, 0, addr);
238*ff6d591cSmrg }
239*ff6d591cSmrg
__tsan_java_release(jptr addr)240*ff6d591cSmrg void __tsan_java_release(jptr addr) {
241*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_release);
242*ff6d591cSmrg DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
243*ff6d591cSmrg DCHECK_NE(jctx, 0);
244*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
245*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
246*ff6d591cSmrg
247*ff6d591cSmrg Release(thr, 0, addr);
248*ff6d591cSmrg }
249*ff6d591cSmrg
__tsan_java_release_store(jptr addr)250*ff6d591cSmrg void __tsan_java_release_store(jptr addr) {
251*ff6d591cSmrg JAVA_FUNC_ENTER(__tsan_java_release);
252*ff6d591cSmrg DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
253*ff6d591cSmrg DCHECK_NE(jctx, 0);
254*ff6d591cSmrg DCHECK_GE(addr, jctx->heap_begin);
255*ff6d591cSmrg DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
256*ff6d591cSmrg
257*ff6d591cSmrg ReleaseStore(thr, 0, addr);
258*ff6d591cSmrg }
259