tsan_rtl_report.cc revision b2c8d695e8b569058b1a8f76e2d2b270d6bd1232
16fbecdd97512bd7d9ccef130e99650d446b50444Alexey Samsonov//===-- tsan_rtl_report.cc ------------------------------------------------===// 27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The LLVM Compiler Infrastructure 47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source 67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details. 77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 1547b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 16ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov#include "sanitizer_common/sanitizer_stackdepot.h" 177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h" 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_symbolize.h" 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_report.h" 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_sync.h" 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h" 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_flags.h" 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovnamespace __tsan { 2715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 28591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonovvoid TsanCheckFailed(const char *file, int line, const char *cond, 29591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov u64 v1, u64 v2) { 3015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov ScopedInRtl in_rtl; 315164ad434eccbfa9ad8097cf25146626313643f9Alexey Samsonov TsanPrintf("FATAL: ThreadSanitizer CHECK failed: " 325164ad434eccbfa9ad8097cf25146626313643f9Alexey Samsonov "%s:%d \"%s\" (0x%zx, 0x%zx)\n", 3315a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov file, line, cond, (uptr)v1, (uptr)v2); 3415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov Die(); 3515a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov} 3615a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Can be overriden by an application/test to intercept reports. 3887dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov#ifdef TSAN_EXTERNAL_HOOKS 3987dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukovbool OnReport(const ReportDesc *rep, bool suppressed); 4087dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov#else 419a46c3b7aeb3a800702b48dd5f8017b0ae7387c7Alexey SamsonovSANITIZER_INTERFACE_ATTRIBUTE 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanybool WEAK OnReport(const ReportDesc *rep, bool suppressed) { 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)rep; 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return suppressed; 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4687dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov#endif 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StackStripMain(ReportStack *stack) { 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *last_frame = 0; 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *last_frame2 = 0; 51f54c0e3321e2381fca3f02faefaaa6639d59c7cfDmitry Vyukov const char *prefix = "__interceptor_"; 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr prefix_len = internal_strlen(prefix); 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *path_prefix = flags()->strip_path_prefix; 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr path_prefix_len = internal_strlen(path_prefix); 5587dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov char *pos; 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (ReportStack *ent = stack; ent; ent = ent->next) { 57d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov if (ent->func && 0 == internal_strncmp(ent->func, prefix, prefix_len)) 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ent->func += prefix_len; 5987dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov if (ent->file && (pos = internal_strstr(ent->file, path_prefix))) 6087dbdf5fd6cb9f1b90a0a97b7675bd8cad8a0264Dmitry Vyukov ent->file = pos + path_prefix_len; 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->file && ent->file[0] == '.' && ent->file[1] == '/') 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ent->file += 2; 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last_frame2 = last_frame; 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last_frame = ent; 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (last_frame2 == 0) 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *last = last_frame->func; 70cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov#ifndef TSAN_GO 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *last2 = last_frame2->func; 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Strip frame above 'main' 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (last2 && 0 == internal_strcmp(last2, "main")) { 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last_frame2->next = 0; 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Strip our internal thread start routine. 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) { 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last_frame2->next = 0; 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Strip global ctors init. 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (last && 0 == internal_strcmp(last, "__do_global_ctors_aux")) { 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last_frame2->next = 0; 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // If both are 0, then we probably just failed to symbolize. 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (last || last2) { 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Ensure that we recovered stack completely. Trimmed stack 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // can actually happen if we do not instrument some code, 850ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov // so it's only a debug print. However we must try hard to not miss it 867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // due to our fault. 870ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov DPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc); 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 89cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov#else 90cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov if (last && 0 == internal_strcmp(last, "schedunlock")) 91cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov last_frame2->next = 0; 92c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#endif 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic ReportStack *SymbolizeStack(const StackTrace& trace) { 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (trace.IsEmpty()) 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return 0; 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *stack = 0; 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr si = 0; si < trace.Size(); si++) { 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We obtain the return address, that is, address of the next instruction, 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // so offset it by 1 byte. 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool is_last = (si == trace.Size() - 1); 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *ent = SymbolizeCode(trace.Get(si) - !is_last); 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(ent, 0); 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *last = ent; 1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (last->next) { 1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last->pc += !is_last; 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last = last->next; 1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last->pc += !is_last; 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany last->next = stack; 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany stack = ent; 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StackStripMain(stack); 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return stack; 1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1187ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyScopedReport::ScopedReport(ReportType typ) { 1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx_ = CTX(); 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc)); 1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_ = new(mem) ReportDesc; 1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->typ = typ; 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx_->report_mtx.Lock(); 1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1267ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyScopedReport::~ScopedReport() { 1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx_->report_mtx.Unlock(); 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->~ReportDesc(); 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_free(rep_); 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ScopedReport::AddStack(const StackTrace *stack) { 1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack **rs = rep_->stacks.PushBack(); 1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *rs = SymbolizeStack(*stack); 1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ScopedReport::AddMemoryAccess(uptr addr, Shadow s, 1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const StackTrace *stack) { 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockReportMop, sizeof(ReportMop)); 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportMop *mop = new(mem) ReportMop; 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->mops.PushBack(mop); 1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->tid = s.tid(); 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->addr = addr + s.addr0(); 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->size = s.size(); 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->write = s.is_write(); 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->nmutex = 0; 1477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->stack = SymbolizeStack(*stack); 1487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ScopedReport::AddThread(const ThreadContext *tctx) { 151ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov for (uptr i = 0; i < rep_->threads.Size(); i++) { 152ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (rep_->threads[i]->id == tctx->tid) 153ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return; 154ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov } 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread)); 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportThread *rt = new(mem) ReportThread(); 1577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->threads.PushBack(rt); 1587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rt->id = tctx->tid; 1597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rt->running = (tctx->status == ThreadStatusRunning); 1607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rt->stack = SymbolizeStack(tctx->creation_stack); 1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1630ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO 164ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukovstatic ThreadContext *FindThread(int unique_id) { 165ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov CTX()->thread_mtx.CheckLocked(); 166ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov for (unsigned i = 0; i < kMaxTid; i++) { 167ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov ThreadContext *tctx = CTX()->threads[i]; 168ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (tctx && tctx->unique_id == unique_id) { 169ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return tctx; 170ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov } 171ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov } 172ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return 0; 173ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov} 1740ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif 175ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov 1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ScopedReport::AddMutex(const SyncVar *s) { 1777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex)); 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportMutex *rm = new(mem) ReportMutex(); 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->mutexes.PushBack(rm); 1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rm->id = 42; 1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rm->stack = SymbolizeStack(s->creation_stack); 1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ScopedReport::AddLocation(uptr addr, uptr size) { 185ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (addr == 0) 186ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return; 187ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov#ifndef TSAN_GO 188ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (allocator()->PointerIsMine((void*)addr)) { 189ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov MBlock *b = user_mblock(0, (void*)addr); 190ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov ThreadContext *tctx = FindThread(b->alloc_tid); 191ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov void *mem = internal_alloc(MBlockReportLoc, sizeof(ReportLocation)); 192ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov ReportLocation *loc = new(mem) ReportLocation(); 193ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov rep_->locs.PushBack(loc); 194ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->type = ReportLocationHeap; 195ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->addr = (uptr)allocator()->GetBlockBegin((void*)addr); 196ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->size = b->size; 197ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->tid = tctx ? tctx->tid : b->alloc_tid; 198ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->name = 0; 199ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->file = 0; 200ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->line = 0; 201ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->stack = 0; 202ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov uptr ssz = 0; 203ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov const uptr *stack = StackDepotGet(b->alloc_stack_id, &ssz); 204ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (stack) { 205ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov StackTrace trace; 206ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov trace.Init(stack, ssz); 207ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->stack = SymbolizeStack(trace); 208ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov } 209ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (tctx) 210ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov AddThread(tctx); 211ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return; 212ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov } 213ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov#endif 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportStack *symb = SymbolizeData(addr); 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (symb) { 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockReportLoc, sizeof(ReportLocation)); 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportLocation *loc = new(mem) ReportLocation(); 2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep_->locs.PushBack(loc); 2197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->type = ReportLocationGlobal; 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->addr = addr; 2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->size = size; 2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->tid = 0; 2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->name = symb->func; 2247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->file = symb->file; 2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->line = symb->line; 2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->stack = 0; 2277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_free(symb); 228ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov return; 2297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2320ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO 233848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovvoid ScopedReport::AddSleep(u32 stack_id) { 234848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov uptr ssz = 0; 235848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov const uptr *stack = StackDepotGet(stack_id, &ssz); 236848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (stack) { 237848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov StackTrace trace; 238848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov trace.Init(stack, ssz); 239848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov rep_->sleep = SymbolizeStack(trace); 240848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 241848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 2420ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif 243848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst ReportDesc *ScopedReport::GetReport() const { 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return rep_; 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 248332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukovvoid RestoreStack(int tid, const u64 epoch, StackTrace *stk) { 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadContext *tctx = CTX()->threads[tid]; 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (tctx == 0) 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Trace* trace = 0; 2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (tctx->status == ThreadStatusRunning) { 2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(tctx->thr); 2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany trace = &tctx->thr->trace; 2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (tctx->status == ThreadStatusFinished 2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany || tctx->status == ThreadStatusDead) { 2589d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov if (tctx->dead_info == 0) 2599d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov return; 2609d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov trace = &tctx->dead_info->trace; 2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&trace->mtx); 2657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const int partidx = (epoch / (kTraceSize / kTraceParts)) % kTraceParts; 2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceHeader* hdr = &trace->headers[partidx]; 2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (epoch < hdr->epoch0) 2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const u64 eend = epoch % kTraceSize; 2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const u64 ebegin = eend / kTracePartSize * kTracePartSize; 271e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n", 272e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx); 27314c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov InternalScopedBuffer<uptr> stack(1024); // FIXME: de-hardcode 1024 2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < hdr->stack0.Size(); i++) { 2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany stack[i] = hdr->stack0.Get(i); 276e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf2(" #%02lu: pc=%zx\n", i, stack[i]); 2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr pos = hdr->stack0.Size(); 2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = ebegin; i <= eend; i++) { 2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Event ev = trace->events[i]; 2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany EventType typ = (EventType)(ev >> 61); 2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr pc = (uptr)(ev & 0xffffffffffffull); 283e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc); 2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == EventTypeMop) { 2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany stack[pos] = pc; 2867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (typ == EventTypeFuncEnter) { 2877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany stack[pos++] = pc; 2887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (typ == EventTypeFuncExit) { 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (pos > 0) 2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pos--; 2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr j = 0; j <= pos; j++) 293e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf2(" #%zu: %zx\n", j, stack[j]); 2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (pos == 0 && stack[0] == 0) 2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pos++; 2981dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov stk->Init(stack.data(), pos); 2997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic bool HandleRacyStacks(ThreadState *thr, const StackTrace (&traces)[2], 3027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr_min, uptr addr_max) { 3037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = CTX(); 3047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool equal_stack = false; 305b2c8d695e8b569058b1a8f76e2d2b270d6bd1232Dmitry Vyukov RacyStacks hash = {}; 3067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (flags()->suppress_equal_stacks) { 3077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hash.hash[0] = md5_hash(traces[0].Begin(), traces[0].Size() * sizeof(uptr)); 3087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hash.hash[1] = md5_hash(traces[1].Begin(), traces[1].Size() * sizeof(uptr)); 3097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { 3107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (hash == ctx->racy_stacks[i]) { 3117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("ThreadSanitizer: suppressing report as doubled (stack)\n"); 3127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany equal_stack = true; 3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool equal_address = false; 3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RacyAddress ra0 = {addr_min, addr_max}; 3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (flags()->suppress_equal_addresses) { 3207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { 3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RacyAddress ra2 = ctx->racy_addresses[i]; 3227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr maxbeg = max(ra0.addr_min, ra2.addr_min); 3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr minend = min(ra0.addr_max, ra2.addr_max); 3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (maxbeg < minend) { 3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("ThreadSanitizer: suppressing report as doubled (addr)\n"); 3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany equal_address = true; 3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 3287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (equal_stack || equal_address) { 3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!equal_stack) 3337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->racy_stacks.PushBack(hash); 3347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!equal_address) 3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->racy_addresses.PushBack(ra0); 3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return true; 3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return false; 3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2], 3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr_min, uptr addr_max) { 3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = CTX(); 3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (flags()->suppress_equal_stacks) { 3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RacyStacks hash; 3467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hash.hash[0] = md5_hash(traces[0].Begin(), traces[0].Size() * sizeof(uptr)); 3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hash.hash[1] = md5_hash(traces[1].Begin(), traces[1].Size() * sizeof(uptr)); 3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->racy_stacks.PushBack(hash); 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (flags()->suppress_equal_addresses) { 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RacyAddress ra0 = {addr_min, addr_max}; 3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->racy_addresses.PushBack(ra0); 3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 356f5820e74ad31eb8352049c880f8d58e286a9b713Dmitry Vyukovbool OutputReport(const ScopedReport &srep, const ReportStack *suppress_stack) { 3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const ReportDesc *rep = srep.GetReport(); 3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool suppressed = IsSuppressed(rep->typ, suppress_stack); 3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany suppressed = OnReport(rep, suppressed); 3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (suppressed) 3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return false; 3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintReport(rep); 3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CTX()->nreported++; 3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return true; 3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid ReportRace(ThreadState *thr) { 3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 369069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov 370069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov bool freed = false; 371069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov { 372069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Shadow s(thr->racy_state[1]); 373069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov freed = s.GetFreedAndReset(); 374069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov thr->racy_state[1] = s.raw(); 375069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov } 376069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov 3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr = ShadowToMem((uptr)thr->racy_shadow_addr); 3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr_min = 0; 3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr_max = 0; 3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr a0 = addr + Shadow(thr->racy_state[0]).addr0(); 3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr a1 = addr + Shadow(thr->racy_state[1]).addr0(); 3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr e0 = a0 + Shadow(thr->racy_state[0]).size(); 3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr e1 = a1 + Shadow(thr->racy_state[1]).size(); 3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr_min = min(a0, a1); 3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr_max = max(e0, e1); 3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (IsExpectedReport(addr_min, addr_max - addr_min)) 3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = CTX(); 3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l0(&ctx->thread_mtx); 3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 394069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov ScopedReport rep(freed ? ReportTypeUseAfterFree : ReportTypeRace); 395069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov const uptr kMop = 2; 396069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov StackTrace traces[kMop]; 397069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov for (uptr i = 0; i < kMop; i++) { 3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow s(thr->racy_state[i]); 3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RestoreStack(s.tid(), s.epoch(), &traces[i]); 4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4010542644830da123babea42f58416487be467c72dDmitry Vyukov // Failure to restore stack of the current thread 4020542644830da123babea42f58416487be467c72dDmitry Vyukov // was observed on free() interceptor called from pthread. 4030542644830da123babea42f58416487be467c72dDmitry Vyukov // Just get the current shadow stack instead. 4040542644830da123babea42f58416487be467c72dDmitry Vyukov if (traces[0].IsEmpty()) 4050542644830da123babea42f58416487be467c72dDmitry Vyukov traces[0].ObtainCurrent(thr, 0); 4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (HandleRacyStacks(thr, traces, addr_min, addr_max)) 4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 410069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov for (uptr i = 0; i < kMop; i++) { 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow s(thr->racy_state[i]); 4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep.AddMemoryAccess(addr, s, &traces[i]); 4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 415069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov for (uptr i = 0; i < kMop; i++) { 4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany FastState s(thr->racy_state[i]); 4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadContext *tctx = ctx->threads[s.tid()]; 4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1) 4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany rep.AddThread(tctx); 4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 423ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov rep.AddLocation(addr_min, addr_max - addr_min); 424ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov 425848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov#ifndef TSAN_GO 426848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov { // NOLINT 427848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov Shadow s(thr->racy_state[1]); 428848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (s.epoch() <= thr->last_sleep_clock.get(s.tid())) 429848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov rep.AddSleep(thr->last_sleep_stack_id); 430848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 431848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov#endif 432848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!OutputReport(rep, rep.GetReport()->mops[0]->stack)) 4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany AddRacyStacks(thr, traces, addr_min, addr_max); 4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4391da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukovvoid PrintCurrentStack(ThreadState *thr, uptr pc) { 4401da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukov StackTrace trace; 4411da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukov trace.ObtainCurrent(thr, pc); 4421da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukov PrintStack(SymbolizeStack(trace)); 4431da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukov} 4441da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukov 4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 446