forked from OSchip/llvm-project
tsan: print alloc stack for Java objects
We maintain information about Java allocations, but for some reason never printed it in reports. Print it. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D106956
This commit is contained in:
parent
dbed061bf1
commit
5237b14087
|
@ -54,6 +54,23 @@ class ScopedJavaFunc {
|
|||
static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
|
||||
static JavaContext *jctx;
|
||||
|
||||
MBlock *JavaHeapBlock(uptr addr, uptr *start) {
|
||||
if (!jctx || addr < jctx->heap_begin ||
|
||||
addr >= jctx->heap_begin + jctx->heap_size)
|
||||
return nullptr;
|
||||
for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
|
||||
p -= kMetaShadowCell) {
|
||||
MBlock *b = ctx->metamap.GetBlock(p);
|
||||
if (!b)
|
||||
continue;
|
||||
if (p + b->siz <= addr)
|
||||
return nullptr;
|
||||
*start = p;
|
||||
return b;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace __tsan
|
||||
|
||||
#define SCOPED_JAVA_FUNC(func) \
|
||||
|
|
|
@ -683,6 +683,7 @@ u32 CurrentStackId(ThreadState *thr, uptr pc);
|
|||
ReportStack *SymbolizeStackId(u32 stack_id);
|
||||
void PrintCurrentStack(ThreadState *thr, uptr pc);
|
||||
void PrintCurrentStackSlow(uptr pc); // uses libunwind
|
||||
MBlock *JavaHeapBlock(uptr addr, uptr *start);
|
||||
|
||||
void Initialize(ThreadState *thr);
|
||||
void MaybeSpawnBackgroundThread();
|
||||
|
|
|
@ -337,12 +337,15 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
|
|||
return;
|
||||
}
|
||||
MBlock *b = 0;
|
||||
uptr block_begin = 0;
|
||||
Allocator *a = allocator();
|
||||
if (a->PointerIsMine((void*)addr)) {
|
||||
void *block_begin = a->GetBlockBegin((void*)addr);
|
||||
block_begin = (uptr)a->GetBlockBegin((void *)addr);
|
||||
if (block_begin)
|
||||
b = ctx->metamap.GetBlock((uptr)block_begin);
|
||||
b = ctx->metamap.GetBlock(block_begin);
|
||||
}
|
||||
if (!b)
|
||||
b = JavaHeapBlock(addr, &block_begin);
|
||||
if (b != 0) {
|
||||
ThreadContext *tctx = FindThreadByTidLocked(b->tid);
|
||||
ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
|
||||
|
|
|
@ -22,6 +22,8 @@ int __tsan_java_release_store(jptr addr);
|
|||
|
||||
void __tsan_read1_pc(jptr addr, jptr pc);
|
||||
void __tsan_write1_pc(jptr addr, jptr pc);
|
||||
void __tsan_func_entry(jptr pc);
|
||||
void __tsan_func_exit();
|
||||
}
|
||||
|
||||
const jptr kExternalPCBit = 1ULL << 60;
|
||||
|
|
|
@ -9,24 +9,40 @@ extern "C" void __tsan_symbolize_external_ex(
|
|||
add_frame(ctx, "MyInnerFunc", "MyInnerFile.java", 1234, 56);
|
||||
add_frame(ctx, "MyOuterFunc", "MyOuterFile.java", 4321, 65);
|
||||
}
|
||||
if (pc == (2345 | kExternalPCBit)) {
|
||||
add_frame(ctx, "Caller1", "CallerFile.java", 111, 22);
|
||||
add_frame(ctx, "Caller2", "CallerFile.java", 333, 44);
|
||||
}
|
||||
if (pc == (3456 | kExternalPCBit)) {
|
||||
add_frame(ctx, "Allocer1", "Alloc.java", 11, 222);
|
||||
add_frame(ctx, "Allocer2", "Alloc.java", 33, 444);
|
||||
}
|
||||
}
|
||||
|
||||
void *Thread(void *p) {
|
||||
barrier_wait(&barrier);
|
||||
__tsan_write1_pc((jptr)p, 1234 | kExternalPCBit);
|
||||
__tsan_func_entry(2345 | kExternalPCBit);
|
||||
__tsan_write1_pc((jptr)p + 16, 1234 | kExternalPCBit);
|
||||
__tsan_func_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
jptr const kHeapSize = 64 * 1024;
|
||||
jptr java_heap[kHeapSize];
|
||||
|
||||
int main() {
|
||||
barrier_init(&barrier, 2);
|
||||
int const kHeapSize = 1024 * 1024;
|
||||
jptr jheap = (jptr)malloc(kHeapSize + 8) + 8;
|
||||
jptr jheap = (jptr)java_heap;
|
||||
__tsan_java_init(jheap, kHeapSize);
|
||||
const int kBlockSize = 16;
|
||||
const int kBlockSize = 32;
|
||||
__tsan_func_entry(3456 | kExternalPCBit);
|
||||
__tsan_java_alloc(jheap, kBlockSize);
|
||||
__tsan_func_exit();
|
||||
pthread_t th;
|
||||
pthread_create(&th, 0, Thread, (void*)jheap);
|
||||
__tsan_write1_pc((jptr)jheap, 1234 | kExternalPCBit);
|
||||
__tsan_func_entry(2345 | kExternalPCBit);
|
||||
__tsan_write1_pc(jheap + 16, 1234 | kExternalPCBit);
|
||||
__tsan_func_exit();
|
||||
barrier_wait(&barrier);
|
||||
pthread_join(th, 0);
|
||||
__tsan_java_free(jheap, kBlockSize);
|
||||
|
@ -35,6 +51,24 @@ int main() {
|
|||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: data race
|
||||
// CHECK: Write
|
||||
// CHECK: #0 MyInnerFunc MyInnerFile.java:1234:56
|
||||
// CHECK: #1 MyOuterFunc MyOuterFile.java:4321:65
|
||||
// CHECK: #2 Caller1 CallerFile.java:111:22
|
||||
// CHECK: #3 Caller2 CallerFile.java:333:44
|
||||
// CHECK-NOT: #4
|
||||
// CHECK: Previous write
|
||||
// CHECK: #0 MyInnerFunc MyInnerFile.java:1234:56
|
||||
// CHECK: #1 MyOuterFunc MyOuterFile.java:4321:65
|
||||
// CHECK: #2 Caller1 CallerFile.java:111:22
|
||||
// CHECK: #3 Caller2 CallerFile.java:333:44
|
||||
// On Linux/glibc #4 is __libc_start_main, but can be something else elsewhere.
|
||||
// CHECK: #4
|
||||
// CHECK: Location is heap block of size 32 at {{.*}} allocated by main thread:
|
||||
// CHECK: #0 __tsan_java_alloc
|
||||
// CHECK: #1 main
|
||||
// CHECK: #2 Allocer1 Alloc.java:11:222
|
||||
// CHECK: #3 Allocer2 Alloc.java:33:444
|
||||
// On Linux/glibc #4 is __libc_start_main, but can be something else elsewhere.
|
||||
// CHECK: #4
|
||||
// CHECK: DONE
|
||||
|
|
Loading…
Reference in New Issue