Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
35266 views
//===-- tsan_interface_java.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of ThreadSanitizer (TSan), a race detector.9//10//===----------------------------------------------------------------------===//1112#include "tsan_interface_java.h"13#include "tsan_rtl.h"14#include "sanitizer_common/sanitizer_internal_defs.h"15#include "sanitizer_common/sanitizer_common.h"16#include "sanitizer_common/sanitizer_placement_new.h"17#include "sanitizer_common/sanitizer_stacktrace.h"18#include "sanitizer_common/sanitizer_procmaps.h"1920using namespace __tsan;2122const jptr kHeapAlignment = 8;2324namespace __tsan {2526struct JavaContext {27const uptr heap_begin;28const uptr heap_size;2930JavaContext(jptr heap_begin, jptr heap_size)31: heap_begin(heap_begin)32, heap_size(heap_size) {33}34};3536static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];37static JavaContext *jctx;3839MBlock *JavaHeapBlock(uptr addr, uptr *start) {40if (!jctx || addr < jctx->heap_begin ||41addr >= jctx->heap_begin + jctx->heap_size)42return nullptr;43for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;44p -= kMetaShadowCell) {45MBlock *b = ctx->metamap.GetBlock(p);46if (!b)47continue;48if (p + b->siz <= addr)49return nullptr;50*start = p;51return b;52}53return nullptr;54}5556} // namespace __tsan5758#define JAVA_FUNC_ENTER(func) \59ThreadState *thr = cur_thread(); \60(void)thr;6162void __tsan_java_init(jptr heap_begin, jptr heap_size) {63JAVA_FUNC_ENTER(__tsan_java_init);64Initialize(thr);65DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);66DCHECK_EQ(jctx, 0);67DCHECK_GT(heap_begin, 0);68DCHECK_GT(heap_size, 0);69DCHECK_EQ(heap_begin % kHeapAlignment, 0);70DCHECK_EQ(heap_size % kHeapAlignment, 0);71DCHECK_LT(heap_begin, heap_begin + heap_size);72jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);73}7475int __tsan_java_fini() {76JAVA_FUNC_ENTER(__tsan_java_fini);77DPrintf("#%d: java_fini()\n", thr->tid);78DCHECK_NE(jctx, 0);79// FIXME(dvyukov): this does not call atexit() callbacks.80int status = Finalize(thr);81DPrintf("#%d: java_fini() = %d\n", thr->tid, status);82return status;83}8485void __tsan_java_alloc(jptr ptr, jptr size) {86JAVA_FUNC_ENTER(__tsan_java_alloc);87DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);88DCHECK_NE(jctx, 0);89DCHECK_NE(size, 0);90DCHECK_EQ(ptr % kHeapAlignment, 0);91DCHECK_EQ(size % kHeapAlignment, 0);92DCHECK_GE(ptr, jctx->heap_begin);93DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);9495OnUserAlloc(thr, 0, ptr, size, false);96}9798void __tsan_java_free(jptr ptr, jptr size) {99JAVA_FUNC_ENTER(__tsan_java_free);100DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);101DCHECK_NE(jctx, 0);102DCHECK_NE(size, 0);103DCHECK_EQ(ptr % kHeapAlignment, 0);104DCHECK_EQ(size % kHeapAlignment, 0);105DCHECK_GE(ptr, jctx->heap_begin);106DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);107108ctx->metamap.FreeRange(thr->proc(), ptr, size, false);109}110111void __tsan_java_move(jptr src, jptr dst, jptr size) {112JAVA_FUNC_ENTER(__tsan_java_move);113DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);114DCHECK_NE(jctx, 0);115DCHECK_NE(size, 0);116DCHECK_EQ(src % kHeapAlignment, 0);117DCHECK_EQ(dst % kHeapAlignment, 0);118DCHECK_EQ(size % kHeapAlignment, 0);119DCHECK_GE(src, jctx->heap_begin);120DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);121DCHECK_GE(dst, jctx->heap_begin);122DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);123DCHECK_NE(dst, src);124DCHECK_NE(size, 0);125126// Assuming it's not running concurrently with threads that do127// memory accesses and mutex operations (stop-the-world phase).128ctx->metamap.MoveMemory(src, dst, size);129130// Clear the destination shadow range.131// We used to move shadow from src to dst, but the trace format does not132// support that anymore as it contains addresses of accesses.133RawShadow *d = MemToShadow(dst);134RawShadow *dend = MemToShadow(dst + size);135ShadowSet(d, dend, Shadow::kEmpty);136}137138jptr __tsan_java_find(jptr *from_ptr, jptr to) {139JAVA_FUNC_ENTER(__tsan_java_find);140DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);141DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);142DCHECK_EQ(to % kHeapAlignment, 0);143DCHECK_GE(*from_ptr, jctx->heap_begin);144DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);145for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {146MBlock *b = ctx->metamap.GetBlock(from);147if (b) {148*from_ptr = from;149return b->siz;150}151}152return 0;153}154155void __tsan_java_finalize() {156JAVA_FUNC_ENTER(__tsan_java_finalize);157DPrintf("#%d: java_finalize()\n", thr->tid);158AcquireGlobal(thr);159}160161void __tsan_java_mutex_lock(jptr addr) {162JAVA_FUNC_ENTER(__tsan_java_mutex_lock);163DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);164DCHECK_NE(jctx, 0);165DCHECK_GE(addr, jctx->heap_begin);166DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);167168MutexPostLock(thr, 0, addr,169MutexFlagLinkerInit | MutexFlagWriteReentrant |170MutexFlagDoPreLockOnPostLock);171}172173void __tsan_java_mutex_unlock(jptr addr) {174JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);175DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);176DCHECK_NE(jctx, 0);177DCHECK_GE(addr, jctx->heap_begin);178DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);179180MutexUnlock(thr, 0, addr);181}182183void __tsan_java_mutex_read_lock(jptr addr) {184JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);185DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);186DCHECK_NE(jctx, 0);187DCHECK_GE(addr, jctx->heap_begin);188DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);189190MutexPostReadLock(thr, 0, addr,191MutexFlagLinkerInit | MutexFlagWriteReentrant |192MutexFlagDoPreLockOnPostLock);193}194195void __tsan_java_mutex_read_unlock(jptr addr) {196JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);197DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);198DCHECK_NE(jctx, 0);199DCHECK_GE(addr, jctx->heap_begin);200DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);201202MutexReadUnlock(thr, 0, addr);203}204205void __tsan_java_mutex_lock_rec(jptr addr, int rec) {206JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);207DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);208DCHECK_NE(jctx, 0);209DCHECK_GE(addr, jctx->heap_begin);210DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);211DCHECK_GT(rec, 0);212213MutexPostLock(thr, 0, addr,214MutexFlagLinkerInit | MutexFlagWriteReentrant |215MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,216rec);217}218219int __tsan_java_mutex_unlock_rec(jptr addr) {220JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);221DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);222DCHECK_NE(jctx, 0);223DCHECK_GE(addr, jctx->heap_begin);224DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);225226return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);227}228229void __tsan_java_acquire(jptr addr) {230JAVA_FUNC_ENTER(__tsan_java_acquire);231DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);232DCHECK_NE(jctx, 0);233DCHECK_GE(addr, jctx->heap_begin);234DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);235236Acquire(thr, 0, addr);237}238239void __tsan_java_release(jptr addr) {240JAVA_FUNC_ENTER(__tsan_java_release);241DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);242DCHECK_NE(jctx, 0);243DCHECK_GE(addr, jctx->heap_begin);244DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);245246Release(thr, 0, addr);247}248249void __tsan_java_release_store(jptr addr) {250JAVA_FUNC_ENTER(__tsan_java_release);251DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);252DCHECK_NE(jctx, 0);253DCHECK_GE(addr, jctx->heap_begin);254DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);255256ReleaseStore(thr, 0, addr);257}258259260