1 //===-- tsan_interface_java.cpp -------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //===----------------------------------------------------------------------===//
13 #include "tsan_interface_java.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"
21 using namespace __tsan
;
23 const jptr kHeapAlignment
= 8;
28 const uptr heap_begin
;
31 JavaContext(jptr heap_begin
, jptr heap_size
)
32 : heap_begin(heap_begin
)
33 , heap_size(heap_size
) {
37 static u64 jctx_buf
[sizeof(JavaContext
) / sizeof(u64
) + 1];
38 static JavaContext
*jctx
;
40 MBlock
*JavaHeapBlock(uptr addr
, uptr
*start
) {
41 if (!jctx
|| addr
< jctx
->heap_begin
||
42 addr
>= jctx
->heap_begin
+ jctx
->heap_size
)
44 for (uptr p
= RoundDown(addr
, kMetaShadowCell
); p
>= jctx
->heap_begin
;
45 p
-= kMetaShadowCell
) {
46 MBlock
*b
= ctx
->metamap
.GetBlock(p
);
49 if (p
+ b
->siz
<= addr
)
59 #define JAVA_FUNC_ENTER(func) \
60 ThreadState *thr = cur_thread(); \
63 void __tsan_java_init(jptr heap_begin
, jptr heap_size
) {
64 JAVA_FUNC_ENTER(__tsan_java_init
);
66 DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr
->tid
, heap_begin
, heap_size
);
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
);
76 int __tsan_java_fini() {
77 JAVA_FUNC_ENTER(__tsan_java_fini
);
78 DPrintf("#%d: java_fini()\n", thr
->tid
);
80 // FIXME(dvyukov): this does not call atexit() callbacks.
81 int status
= Finalize(thr
);
82 DPrintf("#%d: java_fini() = %d\n", thr
->tid
, status
);
86 void __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
);
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
);
96 OnUserAlloc(thr
, 0, ptr
, size
, false);
99 void __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
);
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
);
109 ctx
->metamap
.FreeRange(thr
->proc(), ptr
, size
, false);
112 void __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
);
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
);
127 // Assuming it's not running concurrently with threads that do
128 // memory accesses and mutex operations (stop-the-world phase).
129 ctx
->metamap
.MoveMemory(src
, dst
, size
);
131 // Clear the destination shadow range.
132 // We used to move shadow from src to dst, but the trace format does not
133 // support that anymore as it contains addresses of accesses.
134 RawShadow
*d
= MemToShadow(dst
);
135 RawShadow
*dend
= MemToShadow(dst
+ size
);
136 ShadowSet(d
, dend
, Shadow::kEmpty
);
139 jptr
__tsan_java_find(jptr
*from_ptr
, jptr to
) {
140 JAVA_FUNC_ENTER(__tsan_java_find
);
141 DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr
->tid
, *from_ptr
, to
);
142 DCHECK_EQ((*from_ptr
) % kHeapAlignment
, 0);
143 DCHECK_EQ(to
% kHeapAlignment
, 0);
144 DCHECK_GE(*from_ptr
, jctx
->heap_begin
);
145 DCHECK_LE(to
, jctx
->heap_begin
+ jctx
->heap_size
);
146 for (uptr from
= *from_ptr
; from
< to
; from
+= kHeapAlignment
) {
147 MBlock
*b
= ctx
->metamap
.GetBlock(from
);
156 void __tsan_java_finalize() {
157 JAVA_FUNC_ENTER(__tsan_java_finalize
);
158 DPrintf("#%d: java_finalize()\n", thr
->tid
);
162 void __tsan_java_mutex_lock(jptr addr
) {
163 JAVA_FUNC_ENTER(__tsan_java_mutex_lock
);
164 DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr
->tid
, addr
);
166 DCHECK_GE(addr
, jctx
->heap_begin
);
167 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
169 MutexPostLock(thr
, 0, addr
,
170 MutexFlagLinkerInit
| MutexFlagWriteReentrant
|
171 MutexFlagDoPreLockOnPostLock
);
174 void __tsan_java_mutex_unlock(jptr addr
) {
175 JAVA_FUNC_ENTER(__tsan_java_mutex_unlock
);
176 DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr
->tid
, addr
);
178 DCHECK_GE(addr
, jctx
->heap_begin
);
179 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
181 MutexUnlock(thr
, 0, addr
);
184 void __tsan_java_mutex_read_lock(jptr addr
) {
185 JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock
);
186 DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr
->tid
, addr
);
188 DCHECK_GE(addr
, jctx
->heap_begin
);
189 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
191 MutexPostReadLock(thr
, 0, addr
,
192 MutexFlagLinkerInit
| MutexFlagWriteReentrant
|
193 MutexFlagDoPreLockOnPostLock
);
196 void __tsan_java_mutex_read_unlock(jptr addr
) {
197 JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock
);
198 DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr
->tid
, addr
);
200 DCHECK_GE(addr
, jctx
->heap_begin
);
201 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
203 MutexReadUnlock(thr
, 0, addr
);
206 void __tsan_java_mutex_lock_rec(jptr addr
, int rec
) {
207 JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec
);
208 DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr
->tid
, addr
, rec
);
210 DCHECK_GE(addr
, jctx
->heap_begin
);
211 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
214 MutexPostLock(thr
, 0, addr
,
215 MutexFlagLinkerInit
| MutexFlagWriteReentrant
|
216 MutexFlagDoPreLockOnPostLock
| MutexFlagRecursiveLock
,
220 int __tsan_java_mutex_unlock_rec(jptr addr
) {
221 JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec
);
222 DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr
->tid
, addr
);
224 DCHECK_GE(addr
, jctx
->heap_begin
);
225 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
227 return MutexUnlock(thr
, 0, addr
, MutexFlagRecursiveUnlock
);
230 void __tsan_java_acquire(jptr addr
) {
231 JAVA_FUNC_ENTER(__tsan_java_acquire
);
232 DPrintf("#%d: java_acquire(0x%zx)\n", thr
->tid
, addr
);
234 DCHECK_GE(addr
, jctx
->heap_begin
);
235 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
237 Acquire(thr
, 0, addr
);
240 void __tsan_java_release(jptr addr
) {
241 JAVA_FUNC_ENTER(__tsan_java_release
);
242 DPrintf("#%d: java_release(0x%zx)\n", thr
->tid
, addr
);
244 DCHECK_GE(addr
, jctx
->heap_begin
);
245 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
247 Release(thr
, 0, addr
);
250 void __tsan_java_release_store(jptr addr
) {
251 JAVA_FUNC_ENTER(__tsan_java_release
);
252 DPrintf("#%d: java_release_store(0x%zx)\n", thr
->tid
, addr
);
254 DCHECK_GE(addr
, jctx
->heap_begin
);
255 DCHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
257 ReleaseStore(thr
, 0, addr
);