tsan_interface_java.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of ThreadSanitizer (TSan), a race detector.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #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"
  19. using namespace __tsan;
  20. const jptr kHeapAlignment = 8;
  21. namespace __tsan {
  22. struct JavaContext {
  23. const uptr heap_begin;
  24. const uptr heap_size;
  25. JavaContext(jptr heap_begin, jptr heap_size)
  26. : heap_begin(heap_begin)
  27. , heap_size(heap_size) {
  28. }
  29. };
  30. static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
  31. static JavaContext *jctx;
  32. MBlock *JavaHeapBlock(uptr addr, uptr *start) {
  33. if (!jctx || addr < jctx->heap_begin ||
  34. addr >= jctx->heap_begin + jctx->heap_size)
  35. return nullptr;
  36. for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
  37. p -= kMetaShadowCell) {
  38. MBlock *b = ctx->metamap.GetBlock(p);
  39. if (!b)
  40. continue;
  41. if (p + b->siz <= addr)
  42. return nullptr;
  43. *start = p;
  44. return b;
  45. }
  46. return nullptr;
  47. }
  48. } // namespace __tsan
  49. #define JAVA_FUNC_ENTER(func) \
  50. ThreadState *thr = cur_thread(); \
  51. (void)thr;
  52. void __tsan_java_init(jptr heap_begin, jptr heap_size) {
  53. JAVA_FUNC_ENTER(__tsan_java_init);
  54. Initialize(thr);
  55. DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
  56. DCHECK_EQ(jctx, 0);
  57. DCHECK_GT(heap_begin, 0);
  58. DCHECK_GT(heap_size, 0);
  59. DCHECK_EQ(heap_begin % kHeapAlignment, 0);
  60. DCHECK_EQ(heap_size % kHeapAlignment, 0);
  61. DCHECK_LT(heap_begin, heap_begin + heap_size);
  62. jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
  63. }
  64. int __tsan_java_fini() {
  65. JAVA_FUNC_ENTER(__tsan_java_fini);
  66. DPrintf("#%d: java_fini()\n", thr->tid);
  67. DCHECK_NE(jctx, 0);
  68. // FIXME(dvyukov): this does not call atexit() callbacks.
  69. int status = Finalize(thr);
  70. DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
  71. return status;
  72. }
  73. void __tsan_java_alloc(jptr ptr, jptr size) {
  74. JAVA_FUNC_ENTER(__tsan_java_alloc);
  75. DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
  76. DCHECK_NE(jctx, 0);
  77. DCHECK_NE(size, 0);
  78. DCHECK_EQ(ptr % kHeapAlignment, 0);
  79. DCHECK_EQ(size % kHeapAlignment, 0);
  80. DCHECK_GE(ptr, jctx->heap_begin);
  81. DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
  82. OnUserAlloc(thr, 0, ptr, size, false);
  83. }
  84. void __tsan_java_free(jptr ptr, jptr size) {
  85. JAVA_FUNC_ENTER(__tsan_java_free);
  86. DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
  87. DCHECK_NE(jctx, 0);
  88. DCHECK_NE(size, 0);
  89. DCHECK_EQ(ptr % kHeapAlignment, 0);
  90. DCHECK_EQ(size % kHeapAlignment, 0);
  91. DCHECK_GE(ptr, jctx->heap_begin);
  92. DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
  93. ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
  94. }
  95. void __tsan_java_move(jptr src, jptr dst, jptr size) {
  96. JAVA_FUNC_ENTER(__tsan_java_move);
  97. DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
  98. DCHECK_NE(jctx, 0);
  99. DCHECK_NE(size, 0);
  100. DCHECK_EQ(src % kHeapAlignment, 0);
  101. DCHECK_EQ(dst % kHeapAlignment, 0);
  102. DCHECK_EQ(size % kHeapAlignment, 0);
  103. DCHECK_GE(src, jctx->heap_begin);
  104. DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
  105. DCHECK_GE(dst, jctx->heap_begin);
  106. DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
  107. DCHECK_NE(dst, src);
  108. DCHECK_NE(size, 0);
  109. // Assuming it's not running concurrently with threads that do
  110. // memory accesses and mutex operations (stop-the-world phase).
  111. ctx->metamap.MoveMemory(src, dst, size);
  112. // Clear the destination shadow range.
  113. // We used to move shadow from src to dst, but the trace format does not
  114. // support that anymore as it contains addresses of accesses.
  115. RawShadow *d = MemToShadow(dst);
  116. RawShadow *dend = MemToShadow(dst + size);
  117. ShadowSet(d, dend, Shadow::kEmpty);
  118. }
  119. jptr __tsan_java_find(jptr *from_ptr, jptr to) {
  120. JAVA_FUNC_ENTER(__tsan_java_find);
  121. DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
  122. DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
  123. DCHECK_EQ(to % kHeapAlignment, 0);
  124. DCHECK_GE(*from_ptr, jctx->heap_begin);
  125. DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
  126. for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
  127. MBlock *b = ctx->metamap.GetBlock(from);
  128. if (b) {
  129. *from_ptr = from;
  130. return b->siz;
  131. }
  132. }
  133. return 0;
  134. }
  135. void __tsan_java_finalize() {
  136. JAVA_FUNC_ENTER(__tsan_java_finalize);
  137. DPrintf("#%d: java_finalize()\n", thr->tid);
  138. AcquireGlobal(thr);
  139. }
  140. void __tsan_java_mutex_lock(jptr addr) {
  141. JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
  142. DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
  143. DCHECK_NE(jctx, 0);
  144. DCHECK_GE(addr, jctx->heap_begin);
  145. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  146. MutexPostLock(thr, 0, addr,
  147. MutexFlagLinkerInit | MutexFlagWriteReentrant |
  148. MutexFlagDoPreLockOnPostLock);
  149. }
  150. void __tsan_java_mutex_unlock(jptr addr) {
  151. JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
  152. DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
  153. DCHECK_NE(jctx, 0);
  154. DCHECK_GE(addr, jctx->heap_begin);
  155. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  156. MutexUnlock(thr, 0, addr);
  157. }
  158. void __tsan_java_mutex_read_lock(jptr addr) {
  159. JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
  160. DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
  161. DCHECK_NE(jctx, 0);
  162. DCHECK_GE(addr, jctx->heap_begin);
  163. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  164. MutexPostReadLock(thr, 0, addr,
  165. MutexFlagLinkerInit | MutexFlagWriteReentrant |
  166. MutexFlagDoPreLockOnPostLock);
  167. }
  168. void __tsan_java_mutex_read_unlock(jptr addr) {
  169. JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
  170. DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
  171. DCHECK_NE(jctx, 0);
  172. DCHECK_GE(addr, jctx->heap_begin);
  173. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  174. MutexReadUnlock(thr, 0, addr);
  175. }
  176. void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
  177. JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
  178. DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
  179. DCHECK_NE(jctx, 0);
  180. DCHECK_GE(addr, jctx->heap_begin);
  181. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  182. DCHECK_GT(rec, 0);
  183. MutexPostLock(thr, 0, addr,
  184. MutexFlagLinkerInit | MutexFlagWriteReentrant |
  185. MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
  186. rec);
  187. }
  188. int __tsan_java_mutex_unlock_rec(jptr addr) {
  189. JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
  190. DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
  191. DCHECK_NE(jctx, 0);
  192. DCHECK_GE(addr, jctx->heap_begin);
  193. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  194. return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
  195. }
  196. void __tsan_java_acquire(jptr addr) {
  197. JAVA_FUNC_ENTER(__tsan_java_acquire);
  198. DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
  199. DCHECK_NE(jctx, 0);
  200. DCHECK_GE(addr, jctx->heap_begin);
  201. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  202. Acquire(thr, 0, addr);
  203. }
  204. void __tsan_java_release(jptr addr) {
  205. JAVA_FUNC_ENTER(__tsan_java_release);
  206. DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
  207. DCHECK_NE(jctx, 0);
  208. DCHECK_GE(addr, jctx->heap_begin);
  209. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  210. Release(thr, 0, addr);
  211. }
  212. void __tsan_java_release_store(jptr addr) {
  213. JAVA_FUNC_ENTER(__tsan_java_release);
  214. DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
  215. DCHECK_NE(jctx, 0);
  216. DCHECK_GE(addr, jctx->heap_begin);
  217. DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  218. ReleaseStore(thr, 0, addr);
  219. }