Index: lib/Transforms/Instrumentation/ThreadSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -150,8 +150,8 @@ // Initialize the callbacks. TsanFuncEntry = checkSanitizerInterfaceFunction(M.getOrInsertFunction( "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); - TsanFuncExit = checkSanitizerInterfaceFunction( - M.getOrInsertFunction("__tsan_func_exit", IRB.getVoidTy(), nullptr)); + TsanFuncExit = checkSanitizerInterfaceFunction(M.getOrInsertFunction( + "__tsan_func_exit", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr)); OrdTy = IRB.getInt32Ty(); for (size_t i = 0; i < kNumberOfAccessSizes; ++i) { const unsigned ByteSize = 1U << i; @@ -447,7 +447,7 @@ IRB.CreateCall(TsanFuncEntry, ReturnAddress); for (auto RetInst : RetVec) { IRBuilder<> IRBRet(RetInst); - IRBRet.CreateCall(TsanFuncExit, {}); + IRBRet.CreateCall(TsanFuncExit, ReturnAddress); } Res = true; } Index: projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -279,7 +279,7 @@ } if (!thr_->ignore_interceptors) { ProcessPendingSignals(thr_); - FuncExit(thr_); + FuncExit(thr_, pc_); CheckNoLocks(thr_); } } @@ -496,7 +496,7 @@ CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos); // Unwind the stack. while (thr->shadow_stack_pos > buf->shadow_stack_pos) - FuncExit(thr); + FuncExit(thr, thr->shadow_stack_pos[-1]); ThreadSignalContext *sctx = SigCtx(thr); if (sctx) { sctx->int_signal_send = buf->int_signal_send; Index: projects/compiler-rt/lib/tsan/rtl/tsan_interface.h =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interface.h +++ projects/compiler-rt/lib/tsan/rtl/tsan_interface.h @@ -71,7 +71,7 @@ void __tsan_vptr_update(void **vptr_p, void *new_val); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc); -SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit(); +SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit(void *call_pc); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read_range(void *addr, unsigned long size); // NOLINT Index: projects/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc +++ projects/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc @@ -33,17 +33,18 @@ public: ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l, uptr pc) - : thr_(thr) { + : thr_(thr), pc_(pc) { FuncEntry(thr_, pc); DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l); } ~ScopedAnnotation() { - FuncExit(thr_); + FuncExit(thr_, pc_); CheckNoLocks(thr_); } private: ThreadState *const thr_; + uptr pc_; }; #define SCOPED_ANNOTATION(typ) \ Index: projects/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc +++ projects/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc @@ -466,16 +466,17 @@ public: ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a, morder mo, const char *func) - : thr_(thr) { + : thr_(thr), pc_(pc) { FuncEntry(thr_, pc); DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo); } ~ScopedAtomic() { ProcessPendingSignals(thr_); - FuncExit(thr_); + FuncExit(thr_, pc_); } private: ThreadState *thr_; + uptr pc_; }; static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) { Index: projects/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h +++ projects/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h @@ -104,8 +104,8 @@ FuncEntry(cur_thread(), (uptr)pc); } -void __tsan_func_exit() { - FuncExit(cur_thread()); +void __tsan_func_exit(void *pc) { + FuncExit(cur_thread(), (uptr)pc); } void __tsan_read_range(void *addr, uptr size) { Index: projects/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc +++ projects/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc @@ -39,18 +39,19 @@ class ScopedJavaFunc { public: ScopedJavaFunc(ThreadState *thr, uptr pc) - : thr_(thr) { + : thr_(thr), pc_(pc) { Initialize(thr_); FuncEntry(thr, pc); } ~ScopedJavaFunc() { - FuncExit(thr_); + FuncExit(thr_, pc_); // FIXME(dvyukov): process pending signals. } private: ThreadState *thr_; + uptr pc_; }; static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1]; Index: projects/compiler-rt/lib/tsan/rtl/tsan_rtl.h =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ projects/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -709,7 +709,7 @@ void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc); void FuncEntry(ThreadState *thr, uptr pc); -void FuncExit(ThreadState *thr); +void FuncExit(ThreadState *thr, uptr pc); int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached); void ThreadStart(ThreadState *thr, int tid, uptr os_id); Index: projects/compiler-rt/lib/tsan/rtl/tsan_rtl.cc =================================================================== --- projects/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ projects/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -961,7 +961,7 @@ } ALWAYS_INLINE USED -void FuncExit(ThreadState *thr) { +void FuncExit(ThreadState *thr, uptr pc) { StatInc(thr, StatFuncExit); DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); if (kCollectHistory) { @@ -973,7 +973,14 @@ #ifndef SANITIZER_GO DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); #endif - thr->shadow_stack_pos--; + + // Unwind the shadow stack until we find "pc", because we could have missed + // some matching FuncExit calls, e.g. due to C++ exceptions. + while (true) { + thr->shadow_stack_pos--; + if (thr->shadow_stack_pos[0] == pc) break; + DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack); + } } void ThreadIgnoreBegin(ThreadState *thr, uptr pc) {