xref: /netbsd-src/external/gpl3/gcc/dist/libsanitizer/tsan/tsan_interface_java.cpp (revision ff6d591ca308ed13e9c5ae142cf113a246c2cdc6)
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