13cab2bb3Spatrick //===-- tsan_interface_java.cpp -------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick
133cab2bb3Spatrick #include "tsan_interface_java.h"
143cab2bb3Spatrick #include "tsan_rtl.h"
153cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
163cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
173cab2bb3Spatrick #include "sanitizer_common/sanitizer_placement_new.h"
183cab2bb3Spatrick #include "sanitizer_common/sanitizer_stacktrace.h"
193cab2bb3Spatrick #include "sanitizer_common/sanitizer_procmaps.h"
203cab2bb3Spatrick
213cab2bb3Spatrick using namespace __tsan;
223cab2bb3Spatrick
233cab2bb3Spatrick const jptr kHeapAlignment = 8;
243cab2bb3Spatrick
253cab2bb3Spatrick namespace __tsan {
263cab2bb3Spatrick
273cab2bb3Spatrick struct JavaContext {
283cab2bb3Spatrick const uptr heap_begin;
293cab2bb3Spatrick const uptr heap_size;
303cab2bb3Spatrick
JavaContext__tsan::JavaContext313cab2bb3Spatrick JavaContext(jptr heap_begin, jptr heap_size)
323cab2bb3Spatrick : heap_begin(heap_begin)
333cab2bb3Spatrick , heap_size(heap_size) {
343cab2bb3Spatrick }
353cab2bb3Spatrick };
363cab2bb3Spatrick
373cab2bb3Spatrick static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
383cab2bb3Spatrick static JavaContext *jctx;
393cab2bb3Spatrick
JavaHeapBlock(uptr addr,uptr * start)40*810390e3Srobert MBlock *JavaHeapBlock(uptr addr, uptr *start) {
41*810390e3Srobert if (!jctx || addr < jctx->heap_begin ||
42*810390e3Srobert addr >= jctx->heap_begin + jctx->heap_size)
43*810390e3Srobert return nullptr;
44*810390e3Srobert for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
45*810390e3Srobert p -= kMetaShadowCell) {
46*810390e3Srobert MBlock *b = ctx->metamap.GetBlock(p);
47*810390e3Srobert if (!b)
48*810390e3Srobert continue;
49*810390e3Srobert if (p + b->siz <= addr)
50*810390e3Srobert return nullptr;
51*810390e3Srobert *start = p;
52*810390e3Srobert return b;
53*810390e3Srobert }
54*810390e3Srobert return nullptr;
55*810390e3Srobert }
56*810390e3Srobert
573cab2bb3Spatrick } // namespace __tsan
583cab2bb3Spatrick
59*810390e3Srobert #define JAVA_FUNC_ENTER(func) \
603cab2bb3Spatrick ThreadState *thr = cur_thread(); \
61*810390e3Srobert (void)thr;
623cab2bb3Spatrick
__tsan_java_init(jptr heap_begin,jptr heap_size)633cab2bb3Spatrick void __tsan_java_init(jptr heap_begin, jptr heap_size) {
64*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_init);
65*810390e3Srobert Initialize(thr);
66*810390e3Srobert DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
67*810390e3Srobert DCHECK_EQ(jctx, 0);
68*810390e3Srobert DCHECK_GT(heap_begin, 0);
69*810390e3Srobert DCHECK_GT(heap_size, 0);
70*810390e3Srobert DCHECK_EQ(heap_begin % kHeapAlignment, 0);
71*810390e3Srobert DCHECK_EQ(heap_size % kHeapAlignment, 0);
72*810390e3Srobert DCHECK_LT(heap_begin, heap_begin + heap_size);
733cab2bb3Spatrick jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
743cab2bb3Spatrick }
753cab2bb3Spatrick
__tsan_java_fini()763cab2bb3Spatrick int __tsan_java_fini() {
77*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_fini);
783cab2bb3Spatrick DPrintf("#%d: java_fini()\n", thr->tid);
79*810390e3Srobert DCHECK_NE(jctx, 0);
803cab2bb3Spatrick // FIXME(dvyukov): this does not call atexit() callbacks.
813cab2bb3Spatrick int status = Finalize(thr);
823cab2bb3Spatrick DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
833cab2bb3Spatrick return status;
843cab2bb3Spatrick }
853cab2bb3Spatrick
__tsan_java_alloc(jptr ptr,jptr size)863cab2bb3Spatrick void __tsan_java_alloc(jptr ptr, jptr size) {
87*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_alloc);
88*810390e3Srobert DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
89*810390e3Srobert DCHECK_NE(jctx, 0);
90*810390e3Srobert DCHECK_NE(size, 0);
91*810390e3Srobert DCHECK_EQ(ptr % kHeapAlignment, 0);
92*810390e3Srobert DCHECK_EQ(size % kHeapAlignment, 0);
93*810390e3Srobert DCHECK_GE(ptr, jctx->heap_begin);
94*810390e3Srobert DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
953cab2bb3Spatrick
96*810390e3Srobert OnUserAlloc(thr, 0, ptr, size, false);
973cab2bb3Spatrick }
983cab2bb3Spatrick
__tsan_java_free(jptr ptr,jptr size)993cab2bb3Spatrick void __tsan_java_free(jptr ptr, jptr size) {
100*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_free);
101*810390e3Srobert DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
102*810390e3Srobert DCHECK_NE(jctx, 0);
103*810390e3Srobert DCHECK_NE(size, 0);
104*810390e3Srobert DCHECK_EQ(ptr % kHeapAlignment, 0);
105*810390e3Srobert DCHECK_EQ(size % kHeapAlignment, 0);
106*810390e3Srobert DCHECK_GE(ptr, jctx->heap_begin);
107*810390e3Srobert DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
1083cab2bb3Spatrick
109*810390e3Srobert ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
1103cab2bb3Spatrick }
1113cab2bb3Spatrick
__tsan_java_move(jptr src,jptr dst,jptr size)1123cab2bb3Spatrick void __tsan_java_move(jptr src, jptr dst, jptr size) {
113*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_move);
114*810390e3Srobert DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
115*810390e3Srobert DCHECK_NE(jctx, 0);
116*810390e3Srobert DCHECK_NE(size, 0);
117*810390e3Srobert DCHECK_EQ(src % kHeapAlignment, 0);
118*810390e3Srobert DCHECK_EQ(dst % kHeapAlignment, 0);
119*810390e3Srobert DCHECK_EQ(size % kHeapAlignment, 0);
120*810390e3Srobert DCHECK_GE(src, jctx->heap_begin);
121*810390e3Srobert DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
122*810390e3Srobert DCHECK_GE(dst, jctx->heap_begin);
123*810390e3Srobert DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
124*810390e3Srobert DCHECK_NE(dst, src);
125*810390e3Srobert DCHECK_NE(size, 0);
1263cab2bb3Spatrick
1273cab2bb3Spatrick // Assuming it's not running concurrently with threads that do
1283cab2bb3Spatrick // memory accesses and mutex operations (stop-the-world phase).
1293cab2bb3Spatrick ctx->metamap.MoveMemory(src, dst, size);
1303cab2bb3Spatrick
131*810390e3Srobert // Clear the destination shadow range.
132*810390e3Srobert // We used to move shadow from src to dst, but the trace format does not
133*810390e3Srobert // support that anymore as it contains addresses of accesses.
134*810390e3Srobert RawShadow *d = MemToShadow(dst);
135*810390e3Srobert RawShadow *dend = MemToShadow(dst + size);
136*810390e3Srobert ShadowSet(d, dend, Shadow::kEmpty);
1373cab2bb3Spatrick }
1383cab2bb3Spatrick
__tsan_java_find(jptr * from_ptr,jptr to)1393cab2bb3Spatrick jptr __tsan_java_find(jptr *from_ptr, jptr to) {
140*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_find);
141*810390e3Srobert DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
142*810390e3Srobert DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
143*810390e3Srobert DCHECK_EQ(to % kHeapAlignment, 0);
144*810390e3Srobert DCHECK_GE(*from_ptr, jctx->heap_begin);
145*810390e3Srobert DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
1463cab2bb3Spatrick for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
1473cab2bb3Spatrick MBlock *b = ctx->metamap.GetBlock(from);
1483cab2bb3Spatrick if (b) {
1493cab2bb3Spatrick *from_ptr = from;
1503cab2bb3Spatrick return b->siz;
1513cab2bb3Spatrick }
1523cab2bb3Spatrick }
1533cab2bb3Spatrick return 0;
1543cab2bb3Spatrick }
1553cab2bb3Spatrick
__tsan_java_finalize()1563cab2bb3Spatrick void __tsan_java_finalize() {
157*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_finalize);
158*810390e3Srobert DPrintf("#%d: java_finalize()\n", thr->tid);
159*810390e3Srobert AcquireGlobal(thr);
1603cab2bb3Spatrick }
1613cab2bb3Spatrick
__tsan_java_mutex_lock(jptr addr)1623cab2bb3Spatrick void __tsan_java_mutex_lock(jptr addr) {
163*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
164*810390e3Srobert DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
165*810390e3Srobert DCHECK_NE(jctx, 0);
166*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
167*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1683cab2bb3Spatrick
169*810390e3Srobert MutexPostLock(thr, 0, addr,
170*810390e3Srobert MutexFlagLinkerInit | MutexFlagWriteReentrant |
1713cab2bb3Spatrick MutexFlagDoPreLockOnPostLock);
1723cab2bb3Spatrick }
1733cab2bb3Spatrick
__tsan_java_mutex_unlock(jptr addr)1743cab2bb3Spatrick void __tsan_java_mutex_unlock(jptr addr) {
175*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
176*810390e3Srobert DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
177*810390e3Srobert DCHECK_NE(jctx, 0);
178*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
179*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1803cab2bb3Spatrick
181*810390e3Srobert MutexUnlock(thr, 0, addr);
1823cab2bb3Spatrick }
1833cab2bb3Spatrick
__tsan_java_mutex_read_lock(jptr addr)1843cab2bb3Spatrick void __tsan_java_mutex_read_lock(jptr addr) {
185*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
186*810390e3Srobert DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
187*810390e3Srobert DCHECK_NE(jctx, 0);
188*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
189*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1903cab2bb3Spatrick
191*810390e3Srobert MutexPostReadLock(thr, 0, addr,
192*810390e3Srobert MutexFlagLinkerInit | MutexFlagWriteReentrant |
193*810390e3Srobert MutexFlagDoPreLockOnPostLock);
1943cab2bb3Spatrick }
1953cab2bb3Spatrick
__tsan_java_mutex_read_unlock(jptr addr)1963cab2bb3Spatrick void __tsan_java_mutex_read_unlock(jptr addr) {
197*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
198*810390e3Srobert DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
199*810390e3Srobert DCHECK_NE(jctx, 0);
200*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
201*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2023cab2bb3Spatrick
203*810390e3Srobert MutexReadUnlock(thr, 0, addr);
2043cab2bb3Spatrick }
2053cab2bb3Spatrick
__tsan_java_mutex_lock_rec(jptr addr,int rec)2063cab2bb3Spatrick void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
207*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
208*810390e3Srobert DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
209*810390e3Srobert DCHECK_NE(jctx, 0);
210*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
211*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212*810390e3Srobert DCHECK_GT(rec, 0);
2133cab2bb3Spatrick
214*810390e3Srobert MutexPostLock(thr, 0, addr,
215*810390e3Srobert MutexFlagLinkerInit | MutexFlagWriteReentrant |
216*810390e3Srobert MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
217*810390e3Srobert rec);
2183cab2bb3Spatrick }
2193cab2bb3Spatrick
__tsan_java_mutex_unlock_rec(jptr addr)2203cab2bb3Spatrick int __tsan_java_mutex_unlock_rec(jptr addr) {
221*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
222*810390e3Srobert DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
223*810390e3Srobert DCHECK_NE(jctx, 0);
224*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
225*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2263cab2bb3Spatrick
227*810390e3Srobert return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
2283cab2bb3Spatrick }
2293cab2bb3Spatrick
__tsan_java_acquire(jptr addr)2303cab2bb3Spatrick void __tsan_java_acquire(jptr addr) {
231*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_acquire);
232*810390e3Srobert DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
233*810390e3Srobert DCHECK_NE(jctx, 0);
234*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
235*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2363cab2bb3Spatrick
237*810390e3Srobert Acquire(thr, 0, addr);
2383cab2bb3Spatrick }
2393cab2bb3Spatrick
__tsan_java_release(jptr addr)2403cab2bb3Spatrick void __tsan_java_release(jptr addr) {
241*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_release);
242*810390e3Srobert DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
243*810390e3Srobert DCHECK_NE(jctx, 0);
244*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
245*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2463cab2bb3Spatrick
247*810390e3Srobert Release(thr, 0, addr);
2483cab2bb3Spatrick }
2493cab2bb3Spatrick
__tsan_java_release_store(jptr addr)2503cab2bb3Spatrick void __tsan_java_release_store(jptr addr) {
251*810390e3Srobert JAVA_FUNC_ENTER(__tsan_java_release);
252*810390e3Srobert DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
253*810390e3Srobert DCHECK_NE(jctx, 0);
254*810390e3Srobert DCHECK_GE(addr, jctx->heap_begin);
255*810390e3Srobert DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2563cab2bb3Spatrick
257*810390e3Srobert ReleaseStore(thr, 0, addr);
2583cab2bb3Spatrick }
259