diff --git a/compiler-rt/lib/tsan/rtl/tsan_external.cpp b/compiler-rt/lib/tsan/rtl/tsan_external.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_external.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_external.cpp @@ -60,14 +60,15 @@ #if !SANITIZER_GO -void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessType typ) { +void ExternalAccess(void *addr, uptr caller_pc, uptr tsan_caller_pc, void *tag, + AccessType typ) { CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); ThreadState *thr = cur_thread(); if (caller_pc) FuncEntry(thr, caller_pc); InsertShadowStackFrameForTag(thr, (uptr)tag); bool in_ignored_lib; if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) - MemoryAccess(thr, CALLERPC, (uptr)addr, 1, typ); + MemoryAccess(thr, tsan_caller_pc, (uptr)addr, 1, typ); FuncExit(thr); if (caller_pc) FuncExit(thr); } @@ -112,12 +113,12 @@ SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_read(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessRead); + ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessRead); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_write(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessWrite); + ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessWrite); } } // extern "C" diff --git a/compiler-rt/test/tsan/Darwin/external-swift-debugging.cpp b/compiler-rt/test/tsan/Darwin/external-swift-debugging.cpp --- a/compiler-rt/test/tsan/Darwin/external-swift-debugging.cpp +++ b/compiler-rt/test/tsan/Darwin/external-swift-debugging.cpp @@ -1,6 +1,7 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %deflake %run %t 2>&1 | FileCheck %s +#include #include #import "../test.h" @@ -13,6 +14,9 @@ int *unique_tid_count, void **sleep_trace, unsigned long trace_size); int __tsan_get_report_tag(void *report, unsigned long *tag); +int __tsan_get_report_mop(void *report, unsigned long idx, int *tid, void **addr, + int *size, int *write, int *atomic, void **trace, + unsigned long trace_size); } __attribute__((no_sanitize("thread"), noinline)) @@ -25,7 +29,10 @@ barrier_init(&barrier, 2); fprintf(stderr, "Start.\n"); // CHECK: Start. - + + fprintf(stderr, "ExternalWrite function address: %p\n", &ExternalWrite); + // CHECK: ExternalWrite function address: [[ExternalWrite_addr:0x[0-9a-z]+]] + void *opaque_object = malloc(16); std::thread t1([opaque_object] { ExternalWrite(opaque_object); @@ -37,7 +44,9 @@ }); // CHECK: WARNING: ThreadSanitizer: Swift access race // CHECK: Modifying access of Swift variable at {{.*}} by thread {{.*}} + // CHECK: #0 ExternalWrite // CHECK: Previous modifying access of Swift variable at {{.*}} by thread {{.*}} + // CHECK: #0 ExternalWrite // CHECK: SUMMARY: ThreadSanitizer: Swift access race t1.join(); t2.join(); @@ -55,13 +64,28 @@ __tsan_get_report_data(report, &description, &count, &stack_count, &mop_count, &loc_count, &mutex_count, &thread_count, &unique_tid_count, sleep_trace, 16); - fprintf(stderr, "report type = '%s', count = %d\n", description, count); - // CHECK: report type = 'external-race', count = 0 + fprintf(stderr, "report type = '%s', count = %d, mop_count = %d\n", description, count, mop_count); + // CHECK: report type = 'external-race', count = 0, mop_count = 2 unsigned long tag; __tsan_get_report_tag(report, &tag); fprintf(stderr, "tag = %ld\n", tag); // CHECK: tag = 1 + + int tid, size, write, atomic; + void *addr; + void *trace[16] = {0}; + __tsan_get_report_mop(report, /*idx=*/0, &tid, &addr, &size, &write, &atomic, + trace, 16); + fprintf(stderr, "Racy write trace (1 of 2):\n"); + for (int i = 0; i < 16 && trace[i]; i++) { + Dl_info info; + dladdr(trace[i], &info); + fprintf(stderr, " %d: frame: %p, function: %p %s\n", i, trace[i], + info.dli_saddr, info.dli_sname); + } + // Ensure ExternalWrite() function is top of trace + // CHECK: 0: frame: 0x{{[0-9a-z]+}}, function: [[ExternalWrite_addr]] _Z13ExternalWritePv } // CHECK: Done.