From f754c5f52bf33370d9444463f37ce22d9316f204 Mon Sep 17 00:00:00 2001 From: Joachim Protze Date: Tue, 24 Sep 2019 11:19:02 +0000 Subject: [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 --- lib/tsan/rtl/tsan_interface.h | 5 +++++ lib/tsan/rtl/tsan_interface_inl.h | 8 ++++++++ test/tsan/race_range_pc.cc | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 test/tsan/race_range_pc.cc 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 -- cgit v1.2.1