15a3bb1a4SNico Weber //===-- tsan_interface_java.cpp -------------------------------------------===//
25a3bb1a4SNico Weber //
35a3bb1a4SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45a3bb1a4SNico Weber // See https://llvm.org/LICENSE.txt for license information.
55a3bb1a4SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a3bb1a4SNico Weber //
75a3bb1a4SNico Weber //===----------------------------------------------------------------------===//
85a3bb1a4SNico Weber //
95a3bb1a4SNico Weber // This file is a part of ThreadSanitizer (TSan), a race detector.
105a3bb1a4SNico Weber //
115a3bb1a4SNico Weber //===----------------------------------------------------------------------===//
125a3bb1a4SNico Weber 
135a3bb1a4SNico Weber #include "tsan_interface_java.h"
145a3bb1a4SNico Weber #include "tsan_rtl.h"
155a3bb1a4SNico Weber #include "sanitizer_common/sanitizer_internal_defs.h"
165a3bb1a4SNico Weber #include "sanitizer_common/sanitizer_common.h"
175a3bb1a4SNico Weber #include "sanitizer_common/sanitizer_placement_new.h"
185a3bb1a4SNico Weber #include "sanitizer_common/sanitizer_stacktrace.h"
195a3bb1a4SNico Weber #include "sanitizer_common/sanitizer_procmaps.h"
205a3bb1a4SNico Weber 
21c0fa6322SVitaly Buka using namespace __tsan;
225a3bb1a4SNico Weber 
235a3bb1a4SNico Weber const jptr kHeapAlignment = 8;
245a3bb1a4SNico Weber 
255a3bb1a4SNico Weber namespace __tsan {
265a3bb1a4SNico Weber 
275a3bb1a4SNico Weber struct JavaContext {
285a3bb1a4SNico Weber   const uptr heap_begin;
295a3bb1a4SNico Weber   const uptr heap_size;
305a3bb1a4SNico Weber 
315a3bb1a4SNico Weber   JavaContext(jptr heap_begin, jptr heap_size)
325a3bb1a4SNico Weber       : heap_begin(heap_begin)
335a3bb1a4SNico Weber       , heap_size(heap_size) {
345a3bb1a4SNico Weber   }
355a3bb1a4SNico Weber };
365a3bb1a4SNico Weber 
375a3bb1a4SNico Weber static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
385a3bb1a4SNico Weber static JavaContext *jctx;
395a3bb1a4SNico Weber 
405237b140SDmitry Vyukov MBlock *JavaHeapBlock(uptr addr, uptr *start) {
415237b140SDmitry Vyukov   if (!jctx || addr < jctx->heap_begin ||
425237b140SDmitry Vyukov       addr >= jctx->heap_begin + jctx->heap_size)
435237b140SDmitry Vyukov     return nullptr;
445237b140SDmitry Vyukov   for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
455237b140SDmitry Vyukov        p -= kMetaShadowCell) {
465237b140SDmitry Vyukov     MBlock *b = ctx->metamap.GetBlock(p);
475237b140SDmitry Vyukov     if (!b)
485237b140SDmitry Vyukov       continue;
495237b140SDmitry Vyukov     if (p + b->siz <= addr)
505237b140SDmitry Vyukov       return nullptr;
515237b140SDmitry Vyukov     *start = p;
525237b140SDmitry Vyukov     return b;
535237b140SDmitry Vyukov   }
545237b140SDmitry Vyukov   return nullptr;
555237b140SDmitry Vyukov }
565237b140SDmitry Vyukov 
575a3bb1a4SNico Weber }  // namespace __tsan
585a3bb1a4SNico Weber 
595a3bb1a4SNico Weber #define SCOPED_JAVA_FUNC(func)     \
605a3bb1a4SNico Weber   ThreadState *thr = cur_thread(); \
61*6563bb53SDmitry Vyukov   (void)thr;                       \
625a3bb1a4SNico Weber   /**/
635a3bb1a4SNico Weber 
645a3bb1a4SNico Weber void __tsan_java_init(jptr heap_begin, jptr heap_size) {
655a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_init);
665a3bb1a4SNico Weber   DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
675a3bb1a4SNico Weber   CHECK_EQ(jctx, 0);
685a3bb1a4SNico Weber   CHECK_GT(heap_begin, 0);
695a3bb1a4SNico Weber   CHECK_GT(heap_size, 0);
705a3bb1a4SNico Weber   CHECK_EQ(heap_begin % kHeapAlignment, 0);
715a3bb1a4SNico Weber   CHECK_EQ(heap_size % kHeapAlignment, 0);
725a3bb1a4SNico Weber   CHECK_LT(heap_begin, heap_begin + heap_size);
735a3bb1a4SNico Weber   jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
745a3bb1a4SNico Weber }
755a3bb1a4SNico Weber 
765a3bb1a4SNico Weber int  __tsan_java_fini() {
775a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_fini);
785a3bb1a4SNico Weber   DPrintf("#%d: java_fini()\n", thr->tid);
795a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
805a3bb1a4SNico Weber   // FIXME(dvyukov): this does not call atexit() callbacks.
815a3bb1a4SNico Weber   int status = Finalize(thr);
825a3bb1a4SNico Weber   DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
835a3bb1a4SNico Weber   return status;
845a3bb1a4SNico Weber }
855a3bb1a4SNico Weber 
865a3bb1a4SNico Weber void __tsan_java_alloc(jptr ptr, jptr size) {
875a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_alloc);
885a3bb1a4SNico Weber   DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
895a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
905a3bb1a4SNico Weber   CHECK_NE(size, 0);
915a3bb1a4SNico Weber   CHECK_EQ(ptr % kHeapAlignment, 0);
925a3bb1a4SNico Weber   CHECK_EQ(size % kHeapAlignment, 0);
935a3bb1a4SNico Weber   CHECK_GE(ptr, jctx->heap_begin);
945a3bb1a4SNico Weber   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
955a3bb1a4SNico Weber 
96*6563bb53SDmitry Vyukov   OnUserAlloc(thr, 0, ptr, size, false);
975a3bb1a4SNico Weber }
985a3bb1a4SNico Weber 
995a3bb1a4SNico Weber void __tsan_java_free(jptr ptr, jptr size) {
1005a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_free);
1015a3bb1a4SNico Weber   DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
1025a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
1035a3bb1a4SNico Weber   CHECK_NE(size, 0);
1045a3bb1a4SNico Weber   CHECK_EQ(ptr % kHeapAlignment, 0);
1055a3bb1a4SNico Weber   CHECK_EQ(size % kHeapAlignment, 0);
1065a3bb1a4SNico Weber   CHECK_GE(ptr, jctx->heap_begin);
1075a3bb1a4SNico Weber   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
1085a3bb1a4SNico Weber 
1095a3bb1a4SNico Weber   ctx->metamap.FreeRange(thr->proc(), ptr, size);
1105a3bb1a4SNico Weber }
1115a3bb1a4SNico Weber 
1125a3bb1a4SNico Weber void __tsan_java_move(jptr src, jptr dst, jptr size) {
1135a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_move);
1145a3bb1a4SNico Weber   DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
1155a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
1165a3bb1a4SNico Weber   CHECK_NE(size, 0);
1175a3bb1a4SNico Weber   CHECK_EQ(src % kHeapAlignment, 0);
1185a3bb1a4SNico Weber   CHECK_EQ(dst % kHeapAlignment, 0);
1195a3bb1a4SNico Weber   CHECK_EQ(size % kHeapAlignment, 0);
1205a3bb1a4SNico Weber   CHECK_GE(src, jctx->heap_begin);
1215a3bb1a4SNico Weber   CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
1225a3bb1a4SNico Weber   CHECK_GE(dst, jctx->heap_begin);
1235a3bb1a4SNico Weber   CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
1245a3bb1a4SNico Weber   CHECK_NE(dst, src);
1255a3bb1a4SNico Weber   CHECK_NE(size, 0);
1265a3bb1a4SNico Weber 
1275a3bb1a4SNico Weber   // Assuming it's not running concurrently with threads that do
1285a3bb1a4SNico Weber   // memory accesses and mutex operations (stop-the-world phase).
1295a3bb1a4SNico Weber   ctx->metamap.MoveMemory(src, dst, size);
1305a3bb1a4SNico Weber 
1315a3bb1a4SNico Weber   // Move shadow.
1325a3bb1a4SNico Weber   u64 *s = (u64*)MemToShadow(src);
1335a3bb1a4SNico Weber   u64 *d = (u64*)MemToShadow(dst);
1345a3bb1a4SNico Weber   u64 *send = (u64*)MemToShadow(src + size);
1355a3bb1a4SNico Weber   uptr inc = 1;
1365a3bb1a4SNico Weber   if (dst > src) {
1375a3bb1a4SNico Weber     s = (u64*)MemToShadow(src + size) - 1;
1385a3bb1a4SNico Weber     d = (u64*)MemToShadow(dst + size) - 1;
1395a3bb1a4SNico Weber     send = (u64*)MemToShadow(src) - 1;
1405a3bb1a4SNico Weber     inc = -1;
1415a3bb1a4SNico Weber   }
1425a3bb1a4SNico Weber   for (; s != send; s += inc, d += inc) {
1435a3bb1a4SNico Weber     *d = *s;
1445a3bb1a4SNico Weber     *s = 0;
1455a3bb1a4SNico Weber   }
1465a3bb1a4SNico Weber }
1475a3bb1a4SNico Weber 
1485a3bb1a4SNico Weber jptr __tsan_java_find(jptr *from_ptr, jptr to) {
1495a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_find);
1505a3bb1a4SNico Weber   DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
1515a3bb1a4SNico Weber   CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
1525a3bb1a4SNico Weber   CHECK_EQ(to % kHeapAlignment, 0);
1535a3bb1a4SNico Weber   CHECK_GE(*from_ptr, jctx->heap_begin);
1545a3bb1a4SNico Weber   CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
1555a3bb1a4SNico Weber   for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
1565a3bb1a4SNico Weber     MBlock *b = ctx->metamap.GetBlock(from);
1575a3bb1a4SNico Weber     if (b) {
1585a3bb1a4SNico Weber       *from_ptr = from;
1595a3bb1a4SNico Weber       return b->siz;
1605a3bb1a4SNico Weber     }
1615a3bb1a4SNico Weber   }
1625a3bb1a4SNico Weber   return 0;
1635a3bb1a4SNico Weber }
1645a3bb1a4SNico Weber 
1655a3bb1a4SNico Weber void __tsan_java_finalize() {
1665a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_finalize);
1675a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
1685acdfb7eSDmitry Vyukov   AcquireGlobal(thr);
1695a3bb1a4SNico Weber }
1705a3bb1a4SNico Weber 
1715a3bb1a4SNico Weber void __tsan_java_mutex_lock(jptr addr) {
1725a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
1735a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
1745a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
1755a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
1765a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1775a3bb1a4SNico Weber 
178*6563bb53SDmitry Vyukov   MutexPostLock(thr, 0, addr,
179*6563bb53SDmitry Vyukov                 MutexFlagLinkerInit | MutexFlagWriteReentrant |
1805a3bb1a4SNico Weber                     MutexFlagDoPreLockOnPostLock);
1815a3bb1a4SNico Weber }
1825a3bb1a4SNico Weber 
1835a3bb1a4SNico Weber void __tsan_java_mutex_unlock(jptr addr) {
1845a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
1855a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
1865a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
1875a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
1885a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1895a3bb1a4SNico Weber 
190*6563bb53SDmitry Vyukov   MutexUnlock(thr, 0, addr);
1915a3bb1a4SNico Weber }
1925a3bb1a4SNico Weber 
1935a3bb1a4SNico Weber void __tsan_java_mutex_read_lock(jptr addr) {
1945a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
1955a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
1965a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
1975a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
1985a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
1995a3bb1a4SNico Weber 
200*6563bb53SDmitry Vyukov   MutexPostReadLock(thr, 0, addr,
201*6563bb53SDmitry Vyukov                     MutexFlagLinkerInit | MutexFlagWriteReentrant |
202*6563bb53SDmitry Vyukov                         MutexFlagDoPreLockOnPostLock);
2035a3bb1a4SNico Weber }
2045a3bb1a4SNico Weber 
2055a3bb1a4SNico Weber void __tsan_java_mutex_read_unlock(jptr addr) {
2065a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
2075a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
2085a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2095a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2105a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2115a3bb1a4SNico Weber 
212*6563bb53SDmitry Vyukov   MutexReadUnlock(thr, 0, addr);
2135a3bb1a4SNico Weber }
2145a3bb1a4SNico Weber 
2155a3bb1a4SNico Weber void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
2165a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
2175a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
2185a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2195a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2205a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2215a3bb1a4SNico Weber   CHECK_GT(rec, 0);
2225a3bb1a4SNico Weber 
223*6563bb53SDmitry Vyukov   MutexPostLock(thr, 0, addr,
224*6563bb53SDmitry Vyukov                 MutexFlagLinkerInit | MutexFlagWriteReentrant |
225*6563bb53SDmitry Vyukov                     MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
226*6563bb53SDmitry Vyukov                 rec);
2275a3bb1a4SNico Weber }
2285a3bb1a4SNico Weber 
2295a3bb1a4SNico Weber int __tsan_java_mutex_unlock_rec(jptr addr) {
2305a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
2315a3bb1a4SNico Weber   DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
2325a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2335a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2345a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2355a3bb1a4SNico Weber 
236*6563bb53SDmitry Vyukov   return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
2375a3bb1a4SNico Weber }
2385a3bb1a4SNico Weber 
2395a3bb1a4SNico Weber void __tsan_java_acquire(jptr addr) {
2405a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_acquire);
2415a3bb1a4SNico Weber   DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
2425a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2435a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2445a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2455a3bb1a4SNico Weber 
246*6563bb53SDmitry Vyukov   Acquire(thr, 0, addr);
2475a3bb1a4SNico Weber }
2485a3bb1a4SNico Weber 
2495a3bb1a4SNico Weber void __tsan_java_release(jptr addr) {
2505a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_release);
2515a3bb1a4SNico Weber   DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
2525a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2535a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2545a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2555a3bb1a4SNico Weber 
256*6563bb53SDmitry Vyukov   Release(thr, 0, addr);
2575a3bb1a4SNico Weber }
2585a3bb1a4SNico Weber 
2595a3bb1a4SNico Weber void __tsan_java_release_store(jptr addr) {
2605a3bb1a4SNico Weber   SCOPED_JAVA_FUNC(__tsan_java_release);
2615a3bb1a4SNico Weber   DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
2625a3bb1a4SNico Weber   CHECK_NE(jctx, 0);
2635a3bb1a4SNico Weber   CHECK_GE(addr, jctx->heap_begin);
2645a3bb1a4SNico Weber   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2655a3bb1a4SNico Weber 
266*6563bb53SDmitry Vyukov   ReleaseStore(thr, 0, addr);
2675a3bb1a4SNico Weber }
268