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 @@ -46,10 +46,6 @@ return tag_data ? tag_data->header : nullptr; } -void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) { - FuncEntry(thr, (uptr)®istered_tags[tag]); -} - uptr TagFromShadowStackFrame(uptr pc) { uptr tag_count = atomic_load(&used_tags, memory_order_relaxed); void *pc_ptr = (void *)pc; @@ -60,16 +56,26 @@ #if !SANITIZER_GO -void ExternalAccess(void *addr, uptr caller_pc, uptr tsan_caller_pc, void *tag, - AccessType typ) { +// We need to track tags for individual memory accesses, but there is no space +// in the shadow cells for them. Instead we push/pop them onto the thread +// traces and ignore the extra tag frames when printing reports. +static void PushTag(ThreadState *thr, uptr tag) { + FuncEntry(thr, (uptr)®istered_tags[tag]); +} +static void PopTag(ThreadState *thr) { FuncExit(thr); } + +static 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)); + bool in_ignored_lib; + if (caller_pc && libignore()->IsIgnored(caller_pc, &in_ignored_lib)) + return; + 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, tsan_caller_pc, (uptr)addr, 1, typ); - FuncExit(thr); + PushTag(thr, (uptr)tag); + MemoryAccess(thr, tsan_caller_pc, (uptr)addr, 1, typ); + PopTag(thr); if (caller_pc) FuncExit(thr); }