llvm-project/compiler-rt/test/tsan/java_symbolization.cpp
Dmitry Vyukov 9dad34423b tsan: strip __libc_start_main frame
We strip all frames below main but in some cases it may be not enough.
Namely, when main is instrumented but does not call any other instrumented code.
In this case __tsan_func_entry in main obtains PC pointing to __libc_start_main
(as we pass caller PC to __tsan_func_entry), but nothing obtains PC pointing
to main itself (as main does not call any instrumented code).
In such case we will not have main in the stack, and stripping everything
below main won't work.
So strip __libc_start_main explicitly as well.
But keep stripping of main because __libc_start_main is glibc/linux-specific,
so looking for main is more reliable (and usually main is present in stacks).

Depends on D106957.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D106958
2021-07-28 20:26:42 +02:00

71 lines
2.3 KiB
C++

// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
#include "java.h"
#include <memory.h>
extern "C" void __tsan_symbolize_external_ex(
jptr pc, void (*add_frame)(void *, const char *, const char *, int, int),
void *ctx) {
if (pc == (1234 | kExternalPCBit)) {
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_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);
jptr jheap = (jptr)java_heap;
__tsan_java_init(jheap, kHeapSize);
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_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);
fprintf(stderr, "DONE\n");
return __tsan_java_fini();
}
// 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
// CHECK-NOT: #4
// CHECK: Location is heap block of size 32 at {{.*}} allocated by main thread:
// CHECK: #0 Allocer1 Alloc.java:11:222
// CHECK: #1 Allocer2 Alloc.java:33:444
// CHECK-NOT: #2
// CHECK: DONE