summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Protze <protze@itc.rwth-aachen.de>2019-09-24 11:19:02 +0000
committerJoachim Protze <protze@itc.rwth-aachen.de>2019-09-24 11:19:02 +0000
commitf754c5f52bf33370d9444463f37ce22d9316f204 (patch)
tree5f5760bdbbc20d85f7d65dbc0fb3a7417857ff0a
parentb5c751dcf99002b7cecdc1975ac107dc4fdef652 (diff)
downloadcompiler-rt-f754c5f52bf33370d9444463f37ce22d9316f204.tar.gz
[TSAN] Add read/write range interface functions with PC
Adding annotation function variants __tsan_write_range_pc and __tsan_read_range_pc to annotate ranged access to memory while providing a program counter for the access. Differential Revision: https://reviews.llvm.org/D66885 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@372730 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/tsan/rtl/tsan_interface.h5
-rw-r--r--lib/tsan/rtl/tsan_interface_inl.h8
-rw-r--r--test/tsan/race_range_pc.cc40
3 files changed, 53 insertions, 0 deletions
diff --git a/lib/tsan/rtl/tsan_interface.h b/lib/tsan/rtl/tsan_interface.h
index b2f0f30c4..6d7286ca5 100644
--- a/lib/tsan/rtl/tsan_interface.h
+++ b/lib/tsan/rtl/tsan_interface.h
@@ -94,6 +94,11 @@ void __tsan_read_range(void *addr, unsigned long size);
SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_write_range(void *addr, unsigned long size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_read_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_write_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
+
// User may provide function that would be called right when TSan detects
// an error. The argument 'report' is an opaque pointer that can be used to
// gather additional information using other TSan report API functions.
diff --git a/lib/tsan/rtl/tsan_interface_inl.h b/lib/tsan/rtl/tsan_interface_inl.h
index 193b91b2e..f955ddf99 100644
--- a/lib/tsan/rtl/tsan_interface_inl.h
+++ b/lib/tsan/rtl/tsan_interface_inl.h
@@ -122,3 +122,11 @@ void __tsan_read_range(void *addr, uptr size) {
void __tsan_write_range(void *addr, uptr size) {
MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
}
+
+void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false);
+}
+
+void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true);
+}
diff --git a/test/tsan/race_range_pc.cc b/test/tsan/race_range_pc.cc
new file mode 100644
index 000000000..a4689bd93
--- /dev/null
+++ b/test/tsan/race_range_pc.cc
@@ -0,0 +1,40 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+// This test fails on powerpc64 big endian.
+// The Tsan report is returning wrong information about
+// the location of the race.
+// XFAIL: powerpc64-unknown-linux-gnu
+
+#include "test.h"
+
+typedef unsigned long uptr;
+extern "C" void __tsan_read_range_pc(uptr addr, uptr size, uptr pc);
+extern "C" void __tsan_write_range_pc(uptr addr, uptr size, uptr pc);
+
+void foobar() {
+}
+
+void barbaz() {
+}
+
+void *Thread(void *p) {
+ barrier_wait(&barrier);
+ __tsan_read_range_pc((uptr)p, 32, (uptr)foobar + kPCInc);
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ int a[128];
+ pthread_t th;
+ pthread_create(&th, 0, Thread, (void*)a);
+ __tsan_write_range_pc((uptr)(a+2), 32, (uptr)barbaz + kPCInc);
+ barrier_wait(&barrier);
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: #0 foobar
+// CHECK: #0 barbaz
+// CHECK: DONE