brintos

brintos / llvm-project-archived public Read only

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