1 //===-- tsan_rtl_report.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of ThreadSanitizer (TSan), a race detector. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_common/sanitizer_libc.h" 14 #include "sanitizer_common/sanitizer_placement_new.h" 15 #include "sanitizer_common/sanitizer_stackdepot.h" 16 #include "sanitizer_common/sanitizer_common.h" 17 #include "sanitizer_common/sanitizer_stacktrace.h" 18 #include "tsan_platform.h" 19 #include "tsan_rtl.h" 20 #include "tsan_suppressions.h" 21 #include "tsan_symbolize.h" 22 #include "tsan_report.h" 23 #include "tsan_sync.h" 24 #include "tsan_mman.h" 25 #include "tsan_flags.h" 26 #include "tsan_fd.h" 27 28 namespace __tsan { 29 30 using namespace __sanitizer; 31 32 static ReportStack *SymbolizeStack(StackTrace trace); 33 34 // Can be overriden by an application/test to intercept reports. 35 #ifdef TSAN_EXTERNAL_HOOKS 36 bool OnReport(const ReportDesc *rep, bool suppressed); 37 #else 38 SANITIZER_WEAK_CXX_DEFAULT_IMPL 39 bool OnReport(const ReportDesc *rep, bool suppressed) { 40 (void)rep; 41 return suppressed; 42 } 43 #endif 44 45 SANITIZER_WEAK_DEFAULT_IMPL 46 void __tsan_on_report(const ReportDesc *rep) { 47 (void)rep; 48 } 49 50 static void StackStripMain(SymbolizedStack *frames) { 51 SymbolizedStack *last_frame = nullptr; 52 SymbolizedStack *last_frame2 = nullptr; 53 for (SymbolizedStack *cur = frames; cur; cur = cur->next) { 54 last_frame2 = last_frame; 55 last_frame = cur; 56 } 57 58 if (last_frame2 == 0) 59 return; 60 #if !SANITIZER_GO 61 const char *last = last_frame->info.function; 62 const char *last2 = last_frame2->info.function; 63 // Strip frame above 'main' 64 if (last2 && 0 == internal_strcmp(last2, "main")) { 65 last_frame->ClearAll(); 66 last_frame2->next = nullptr; 67 // Strip our internal thread start routine. 68 } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) { 69 last_frame->ClearAll(); 70 last_frame2->next = nullptr; 71 // Strip global ctors init, .preinit_array and main caller. 72 } else if (last && (0 == internal_strcmp(last, "__do_global_ctors_aux") || 73 0 == internal_strcmp(last, "__libc_csu_init") || 74 0 == internal_strcmp(last, "__libc_start_main"))) { 75 last_frame->ClearAll(); 76 last_frame2->next = nullptr; 77 // If both are 0, then we probably just failed to symbolize. 78 } else if (last || last2) { 79 // Ensure that we recovered stack completely. Trimmed stack 80 // can actually happen if we do not instrument some code, 81 // so it's only a debug print. However we must try hard to not miss it 82 // due to our fault. 83 DPrintf("Bottom stack frame is missed\n"); 84 } 85 #else 86 // The last frame always point into runtime (gosched0, goexit0, runtime.main). 87 last_frame->ClearAll(); 88 last_frame2->next = nullptr; 89 #endif 90 } 91 92 ReportStack *SymbolizeStackId(u32 stack_id) { 93 if (stack_id == 0) 94 return 0; 95 StackTrace stack = StackDepotGet(stack_id); 96 if (stack.trace == nullptr) 97 return nullptr; 98 return SymbolizeStack(stack); 99 } 100 101 static ReportStack *SymbolizeStack(StackTrace trace) { 102 if (trace.size == 0) 103 return 0; 104 SymbolizedStack *top = nullptr; 105 for (uptr si = 0; si < trace.size; si++) { 106 const uptr pc = trace.trace[si]; 107 uptr pc1 = pc; 108 // We obtain the return address, but we're interested in the previous 109 // instruction. 110 if ((pc & kExternalPCBit) == 0) 111 pc1 = StackTrace::GetPreviousInstructionPc(pc); 112 SymbolizedStack *ent = SymbolizeCode(pc1); 113 CHECK_NE(ent, 0); 114 SymbolizedStack *last = ent; 115 while (last->next) { 116 last->info.address = pc; // restore original pc for report 117 last = last->next; 118 } 119 last->info.address = pc; // restore original pc for report 120 last->next = top; 121 top = ent; 122 } 123 StackStripMain(top); 124 125 auto *stack = New<ReportStack>(); 126 stack->frames = top; 127 return stack; 128 } 129 130 bool ShouldReport(ThreadState *thr, ReportType typ) { 131 // We set thr->suppress_reports in the fork context. 132 // Taking any locking in the fork context can lead to deadlocks. 133 // If any locks are already taken, it's too late to do this check. 134 CheckedMutex::CheckNoLocks(); 135 // For the same reason check we didn't lock thread_registry yet. 136 if (SANITIZER_DEBUG) 137 ThreadRegistryLock l(&ctx->thread_registry); 138 if (!flags()->report_bugs || thr->suppress_reports) 139 return false; 140 switch (typ) { 141 case ReportTypeSignalUnsafe: 142 return flags()->report_signal_unsafe; 143 case ReportTypeThreadLeak: 144 #if !SANITIZER_GO 145 // It's impossible to join phantom threads 146 // in the child after fork. 147 if (ctx->after_multithreaded_fork) 148 return false; 149 #endif 150 return flags()->report_thread_leaks; 151 case ReportTypeMutexDestroyLocked: 152 return flags()->report_destroy_locked; 153 default: 154 return true; 155 } 156 } 157 158 ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) { 159 ctx->thread_registry.CheckLocked(); 160 rep_ = New<ReportDesc>(); 161 rep_->typ = typ; 162 rep_->tag = tag; 163 ctx->report_mtx.Lock(); 164 } 165 166 ScopedReportBase::~ScopedReportBase() { 167 ctx->report_mtx.Unlock(); 168 DestroyAndFree(rep_); 169 } 170 171 void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) { 172 ReportStack **rs = rep_->stacks.PushBack(); 173 *rs = SymbolizeStack(stack); 174 (*rs)->suppressable = suppressable; 175 } 176 177 void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, 178 StackTrace stack, const MutexSet *mset) { 179 auto *mop = New<ReportMop>(); 180 rep_->mops.PushBack(mop); 181 mop->tid = s.tid(); 182 mop->addr = addr + s.addr0(); 183 mop->size = s.size(); 184 mop->write = s.IsWrite(); 185 mop->atomic = s.IsAtomic(); 186 mop->stack = SymbolizeStack(stack); 187 mop->external_tag = external_tag; 188 if (mop->stack) 189 mop->stack->suppressable = true; 190 for (uptr i = 0; i < mset->Size(); i++) { 191 MutexSet::Desc d = mset->Get(i); 192 u64 mid = this->AddMutex(d.id); 193 ReportMopMutex mtx = {mid, d.write}; 194 mop->mset.PushBack(mtx); 195 } 196 } 197 198 void ScopedReportBase::AddUniqueTid(Tid unique_tid) { 199 rep_->unique_tids.PushBack(unique_tid); 200 } 201 202 void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) { 203 for (uptr i = 0; i < rep_->threads.Size(); i++) { 204 if ((u32)rep_->threads[i]->id == tctx->tid) 205 return; 206 } 207 auto *rt = New<ReportThread>(); 208 rep_->threads.PushBack(rt); 209 rt->id = tctx->tid; 210 rt->os_id = tctx->os_id; 211 rt->running = (tctx->status == ThreadStatusRunning); 212 rt->name = internal_strdup(tctx->name); 213 rt->parent_tid = tctx->parent_tid; 214 rt->thread_type = tctx->thread_type; 215 rt->stack = 0; 216 rt->stack = SymbolizeStackId(tctx->creation_stack_id); 217 if (rt->stack) 218 rt->stack->suppressable = suppressable; 219 } 220 221 #if !SANITIZER_GO 222 static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) { 223 int unique_id = *(int *)arg; 224 return tctx->unique_id == (u32)unique_id; 225 } 226 227 static ThreadContext *FindThreadByUidLocked(Tid unique_id) { 228 ctx->thread_registry.CheckLocked(); 229 return static_cast<ThreadContext *>( 230 ctx->thread_registry.FindThreadContextLocked( 231 FindThreadByUidLockedCallback, &unique_id)); 232 } 233 234 static ThreadContext *FindThreadByTidLocked(Tid tid) { 235 ctx->thread_registry.CheckLocked(); 236 return static_cast<ThreadContext *>( 237 ctx->thread_registry.GetThreadLocked(tid)); 238 } 239 240 static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) { 241 uptr addr = (uptr)arg; 242 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base); 243 if (tctx->status != ThreadStatusRunning) 244 return false; 245 ThreadState *thr = tctx->thr; 246 CHECK(thr); 247 return ((addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size) || 248 (addr >= thr->tls_addr && addr < thr->tls_addr + thr->tls_size)); 249 } 250 251 ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) { 252 ctx->thread_registry.CheckLocked(); 253 ThreadContext *tctx = 254 static_cast<ThreadContext *>(ctx->thread_registry.FindThreadContextLocked( 255 IsInStackOrTls, (void *)addr)); 256 if (!tctx) 257 return 0; 258 ThreadState *thr = tctx->thr; 259 CHECK(thr); 260 *is_stack = (addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size); 261 return tctx; 262 } 263 #endif 264 265 void ScopedReportBase::AddThread(Tid unique_tid, bool suppressable) { 266 #if !SANITIZER_GO 267 if (const ThreadContext *tctx = FindThreadByUidLocked(unique_tid)) 268 AddThread(tctx, suppressable); 269 #endif 270 } 271 272 void ScopedReportBase::AddMutex(const SyncVar *s) { 273 for (uptr i = 0; i < rep_->mutexes.Size(); i++) { 274 if (rep_->mutexes[i]->id == s->uid) 275 return; 276 } 277 auto *rm = New<ReportMutex>(); 278 rep_->mutexes.PushBack(rm); 279 rm->id = s->uid; 280 rm->addr = s->addr; 281 rm->destroyed = false; 282 rm->stack = SymbolizeStackId(s->creation_stack_id); 283 } 284 285 u64 ScopedReportBase::AddMutex(u64 id) { 286 u64 uid = 0; 287 u64 mid = id; 288 uptr addr = SyncVar::SplitId(id, &uid); 289 SyncVar *s = ctx->metamap.GetSyncIfExists(addr); 290 // Check that the mutex is still alive. 291 // Another mutex can be created at the same address, 292 // so check uid as well. 293 if (s && s->CheckId(uid)) { 294 Lock l(&s->mtx); 295 mid = s->uid; 296 AddMutex(s); 297 } else { 298 AddDeadMutex(id); 299 } 300 return mid; 301 } 302 303 void ScopedReportBase::AddDeadMutex(u64 id) { 304 for (uptr i = 0; i < rep_->mutexes.Size(); i++) { 305 if (rep_->mutexes[i]->id == id) 306 return; 307 } 308 auto *rm = New<ReportMutex>(); 309 rep_->mutexes.PushBack(rm); 310 rm->id = id; 311 rm->addr = 0; 312 rm->destroyed = true; 313 rm->stack = 0; 314 } 315 316 void ScopedReportBase::AddLocation(uptr addr, uptr size) { 317 if (addr == 0) 318 return; 319 #if !SANITIZER_GO 320 int fd = -1; 321 Tid creat_tid = kInvalidTid; 322 StackID creat_stack = 0; 323 if (FdLocation(addr, &fd, &creat_tid, &creat_stack)) { 324 auto *loc = New<ReportLocation>(); 325 loc->type = ReportLocationFD; 326 loc->fd = fd; 327 loc->tid = creat_tid; 328 loc->stack = SymbolizeStackId(creat_stack); 329 rep_->locs.PushBack(loc); 330 ThreadContext *tctx = FindThreadByUidLocked(creat_tid); 331 if (tctx) 332 AddThread(tctx); 333 return; 334 } 335 MBlock *b = 0; 336 uptr block_begin = 0; 337 Allocator *a = allocator(); 338 if (a->PointerIsMine((void*)addr)) { 339 block_begin = (uptr)a->GetBlockBegin((void *)addr); 340 if (block_begin) 341 b = ctx->metamap.GetBlock(block_begin); 342 } 343 if (!b) 344 b = JavaHeapBlock(addr, &block_begin); 345 if (b != 0) { 346 ThreadContext *tctx = FindThreadByTidLocked(b->tid); 347 auto *loc = New<ReportLocation>(); 348 loc->type = ReportLocationHeap; 349 loc->heap_chunk_start = (uptr)allocator()->GetBlockBegin((void *)addr); 350 loc->heap_chunk_size = b->siz; 351 loc->external_tag = b->tag; 352 loc->tid = tctx ? tctx->tid : b->tid; 353 loc->stack = SymbolizeStackId(b->stk); 354 rep_->locs.PushBack(loc); 355 if (tctx) 356 AddThread(tctx); 357 return; 358 } 359 bool is_stack = false; 360 if (ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack)) { 361 auto *loc = New<ReportLocation>(); 362 loc->type = is_stack ? ReportLocationStack : ReportLocationTLS; 363 loc->tid = tctx->tid; 364 rep_->locs.PushBack(loc); 365 AddThread(tctx); 366 } 367 #endif 368 if (ReportLocation *loc = SymbolizeData(addr)) { 369 loc->suppressable = true; 370 rep_->locs.PushBack(loc); 371 return; 372 } 373 } 374 375 #if !SANITIZER_GO 376 void ScopedReportBase::AddSleep(StackID stack_id) { 377 rep_->sleep = SymbolizeStackId(stack_id); 378 } 379 #endif 380 381 void ScopedReportBase::SetCount(int count) { rep_->count = count; } 382 383 const ReportDesc *ScopedReportBase::GetReport() const { return rep_; } 384 385 ScopedReport::ScopedReport(ReportType typ, uptr tag) 386 : ScopedReportBase(typ, tag) {} 387 388 ScopedReport::~ScopedReport() {} 389 390 void RestoreStack(Tid tid, const u64 epoch, VarSizeStackTrace *stk, 391 MutexSet *mset, uptr *tag) { 392 // This function restores stack trace and mutex set for the thread/epoch. 393 // It does so by getting stack trace and mutex set at the beginning of 394 // trace part, and then replaying the trace till the given epoch. 395 Trace* trace = ThreadTrace(tid); 396 ReadLock l(&trace->mtx); 397 const int partidx = (epoch / kTracePartSize) % TraceParts(); 398 TraceHeader* hdr = &trace->headers[partidx]; 399 if (epoch < hdr->epoch0 || epoch >= hdr->epoch0 + kTracePartSize) 400 return; 401 CHECK_EQ(RoundDown(epoch, kTracePartSize), hdr->epoch0); 402 const u64 epoch0 = RoundDown(epoch, TraceSize()); 403 const u64 eend = epoch % TraceSize(); 404 const u64 ebegin = RoundDown(eend, kTracePartSize); 405 DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n", 406 tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx); 407 Vector<uptr> stack; 408 stack.Resize(hdr->stack0.size + 64); 409 for (uptr i = 0; i < hdr->stack0.size; i++) { 410 stack[i] = hdr->stack0.trace[i]; 411 DPrintf2(" #%02zu: pc=%zx\n", i, stack[i]); 412 } 413 if (mset) 414 *mset = hdr->mset0; 415 uptr pos = hdr->stack0.size; 416 Event *events = (Event*)GetThreadTrace(tid); 417 for (uptr i = ebegin; i <= eend; i++) { 418 Event ev = events[i]; 419 EventType typ = (EventType)(ev >> kEventPCBits); 420 uptr pc = (uptr)(ev & ((1ull << kEventPCBits) - 1)); 421 DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc); 422 if (typ == EventTypeMop) { 423 stack[pos] = pc; 424 } else if (typ == EventTypeFuncEnter) { 425 if (stack.Size() < pos + 2) 426 stack.Resize(pos + 2); 427 stack[pos++] = pc; 428 } else if (typ == EventTypeFuncExit) { 429 if (pos > 0) 430 pos--; 431 } 432 if (mset) { 433 if (typ == EventTypeLock) { 434 mset->Add(pc, true, epoch0 + i); 435 } else if (typ == EventTypeUnlock) { 436 mset->Del(pc, true); 437 } else if (typ == EventTypeRLock) { 438 mset->Add(pc, false, epoch0 + i); 439 } else if (typ == EventTypeRUnlock) { 440 mset->Del(pc, false); 441 } 442 } 443 for (uptr j = 0; j <= pos; j++) 444 DPrintf2(" #%zu: %zx\n", j, stack[j]); 445 } 446 if (pos == 0 && stack[0] == 0) 447 return; 448 pos++; 449 stk->Init(&stack[0], pos); 450 ExtractTagFromStack(stk, tag); 451 } 452 453 namespace v3 { 454 455 // Replays the trace up to last_pos position in the last part 456 // or up to the provided epoch/sid (whichever is earlier) 457 // and calls the provided function f for each event. 458 template <typename Func> 459 void TraceReplay(Trace *trace, TracePart *last, Event *last_pos, Sid sid, 460 Epoch epoch, Func f) { 461 TracePart *part = trace->parts.Front(); 462 Sid ev_sid = kFreeSid; 463 Epoch ev_epoch = kEpochOver; 464 for (;;) { 465 DCHECK_EQ(part->trace, trace); 466 // Note: an event can't start in the last element. 467 // Since an event can take up to 2 elements, 468 // we ensure we have at least 2 before adding an event. 469 Event *end = &part->events[TracePart::kSize - 1]; 470 if (part == last) 471 end = last_pos; 472 for (Event *evp = &part->events[0]; evp < end; evp++) { 473 Event *evp0 = evp; 474 if (!evp->is_access && !evp->is_func) { 475 switch (evp->type) { 476 case EventType::kTime: { 477 auto *ev = reinterpret_cast<EventTime *>(evp); 478 ev_sid = static_cast<Sid>(ev->sid); 479 ev_epoch = static_cast<Epoch>(ev->epoch); 480 if (ev_sid == sid && ev_epoch > epoch) 481 return; 482 break; 483 } 484 case EventType::kAccessExt: 485 FALLTHROUGH; 486 case EventType::kAccessRange: 487 FALLTHROUGH; 488 case EventType::kLock: 489 FALLTHROUGH; 490 case EventType::kRLock: 491 // These take 2 Event elements. 492 evp++; 493 break; 494 case EventType::kUnlock: 495 // This takes 1 Event element. 496 break; 497 } 498 } 499 CHECK_NE(ev_sid, kFreeSid); 500 CHECK_NE(ev_epoch, kEpochOver); 501 f(ev_sid, ev_epoch, evp0); 502 } 503 if (part == last) 504 return; 505 part = trace->parts.Next(part); 506 CHECK(part); 507 } 508 CHECK(0); 509 } 510 511 static void RestoreStackMatch(VarSizeStackTrace *pstk, MutexSet *pmset, 512 Vector<uptr> *stack, MutexSet *mset, uptr pc, 513 bool *found) { 514 DPrintf2(" MATCHED\n"); 515 *pmset = *mset; 516 stack->PushBack(pc); 517 pstk->Init(&(*stack)[0], stack->Size()); 518 stack->PopBack(); 519 *found = true; 520 } 521 522 // Checks if addr1|size1 is fully contained in addr2|size2. 523 // We check for fully contained instread of just overlapping 524 // because a memory access is always traced once, but can be 525 // split into multiple accesses in the shadow. 526 static constexpr bool IsWithinAccess(uptr addr1, uptr size1, uptr addr2, 527 uptr size2) { 528 return addr1 >= addr2 && addr1 + size1 <= addr2 + size2; 529 } 530 531 // Replays the trace of thread tid up to the target event identified 532 // by sid/epoch/addr/size/typ and restores and returns stack, mutex set 533 // and tag for that event. If there are multiple such events, it returns 534 // the last one. Returns false if the event is not present in the trace. 535 bool RestoreStack(Tid tid, EventType type, Sid sid, Epoch epoch, uptr addr, 536 uptr size, AccessType typ, VarSizeStackTrace *pstk, 537 MutexSet *pmset, uptr *ptag) { 538 // This function restores stack trace and mutex set for the thread/epoch. 539 // It does so by getting stack trace and mutex set at the beginning of 540 // trace part, and then replaying the trace till the given epoch. 541 DPrintf2("RestoreStack: tid=%u sid=%u@%u addr=0x%zx/%zu typ=%x\n", tid, 542 static_cast<int>(sid), static_cast<int>(epoch), addr, size, 543 static_cast<int>(typ)); 544 ctx->slot_mtx.CheckLocked(); // needed to prevent trace part recycling 545 ctx->thread_registry.CheckLocked(); 546 ThreadContext *tctx = 547 static_cast<ThreadContext *>(ctx->thread_registry.GetThreadLocked(tid)); 548 Trace *trace = &tctx->trace; 549 // Snapshot first/last parts and the current position in the last part. 550 TracePart *first_part; 551 TracePart *last_part; 552 Event *last_pos; 553 { 554 Lock lock(&trace->mtx); 555 first_part = trace->parts.Front(); 556 if (!first_part) 557 return false; 558 last_part = trace->parts.Back(); 559 last_pos = trace->final_pos; 560 if (tctx->thr) 561 last_pos = (Event *)atomic_load_relaxed(&tctx->thr->trace_pos); 562 } 563 // Too large for stack. 564 alignas(MutexSet) static char mset_storage[sizeof(MutexSet)]; 565 MutexSet &mset = *new (mset_storage) MutexSet(); 566 Vector<uptr> stack; 567 uptr prev_pc = 0; 568 bool found = false; 569 bool is_read = typ & kAccessRead; 570 bool is_atomic = typ & kAccessAtomic; 571 bool is_free = typ & kAccessFree; 572 TraceReplay( 573 trace, last_part, last_pos, sid, epoch, 574 [&](Sid ev_sid, Epoch ev_epoch, Event *evp) { 575 bool match = ev_sid == sid && ev_epoch == epoch; 576 if (evp->is_access) { 577 if (evp->is_func == 0 && evp->type == EventType::kAccessExt && 578 evp->_ == 0) // NopEvent 579 return; 580 auto *ev = reinterpret_cast<EventAccess *>(evp); 581 uptr ev_addr = RestoreAddr(ev->addr); 582 uptr ev_size = 1 << ev->size_log; 583 uptr ev_pc = 584 prev_pc + ev->pc_delta - (1 << (EventAccess::kPCBits - 1)); 585 prev_pc = ev_pc; 586 DPrintf2(" Access: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc, 587 ev_addr, ev_size, ev->is_read, ev->is_atomic); 588 if (match && type == EventType::kAccessExt && 589 IsWithinAccess(addr, size, ev_addr, ev_size) && 590 is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free) 591 RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); 592 return; 593 } 594 if (evp->is_func) { 595 auto *ev = reinterpret_cast<EventFunc *>(evp); 596 if (ev->pc) { 597 DPrintf2(" FuncEnter: pc=0x%llx\n", ev->pc); 598 stack.PushBack(ev->pc); 599 } else { 600 DPrintf2(" FuncExit\n"); 601 CHECK(stack.Size()); 602 stack.PopBack(); 603 } 604 return; 605 } 606 switch (evp->type) { 607 case EventType::kAccessExt: { 608 auto *ev = reinterpret_cast<EventAccessExt *>(evp); 609 uptr ev_addr = RestoreAddr(ev->addr); 610 uptr ev_size = 1 << ev->size_log; 611 prev_pc = ev->pc; 612 DPrintf2(" AccessExt: pc=0x%llx addr=0x%zx/%zu type=%u/%u\n", 613 ev->pc, ev_addr, ev_size, ev->is_read, ev->is_atomic); 614 if (match && type == EventType::kAccessExt && 615 IsWithinAccess(addr, size, ev_addr, ev_size) && 616 is_read == ev->is_read && is_atomic == ev->is_atomic && 617 !is_free) 618 RestoreStackMatch(pstk, pmset, &stack, &mset, ev->pc, &found); 619 break; 620 } 621 case EventType::kAccessRange: { 622 auto *ev = reinterpret_cast<EventAccessRange *>(evp); 623 uptr ev_addr = RestoreAddr(ev->addr); 624 uptr ev_size = 625 (ev->size_hi << EventAccessRange::kSizeLoBits) + ev->size_lo; 626 uptr ev_pc = RestoreAddr(ev->pc); 627 prev_pc = ev_pc; 628 DPrintf2(" Range: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc, 629 ev_addr, ev_size, ev->is_read, ev->is_free); 630 if (match && type == EventType::kAccessExt && 631 IsWithinAccess(addr, size, ev_addr, ev_size) && 632 is_read == ev->is_read && !is_atomic && is_free == ev->is_free) 633 RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); 634 break; 635 } 636 case EventType::kLock: 637 FALLTHROUGH; 638 case EventType::kRLock: { 639 auto *ev = reinterpret_cast<EventLock *>(evp); 640 bool is_write = ev->type == EventType::kLock; 641 uptr ev_addr = RestoreAddr(ev->addr); 642 uptr ev_pc = RestoreAddr(ev->pc); 643 StackID stack_id = 644 (ev->stack_hi << EventLock::kStackIDLoBits) + ev->stack_lo; 645 DPrintf2(" Lock: pc=0x%zx addr=0x%zx stack=%u write=%d\n", ev_pc, 646 ev_addr, stack_id, is_write); 647 mset.AddAddr(ev_addr, stack_id, is_write); 648 // Events with ev_pc == 0 are written to the beginning of trace 649 // part as initial mutex set (are not real). 650 if (match && type == EventType::kLock && addr == ev_addr && ev_pc) 651 RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); 652 break; 653 } 654 case EventType::kUnlock: { 655 auto *ev = reinterpret_cast<EventUnlock *>(evp); 656 uptr ev_addr = RestoreAddr(ev->addr); 657 DPrintf2(" Unlock: addr=0x%zx\n", ev_addr); 658 mset.DelAddr(ev_addr); 659 break; 660 } 661 case EventType::kTime: 662 // TraceReplay already extracted sid/epoch from it, 663 // nothing else to do here. 664 break; 665 } 666 }); 667 ExtractTagFromStack(pstk, ptag); 668 return found; 669 } 670 671 } // namespace v3 672 673 static bool FindRacyStacks(const RacyStacks &hash) { 674 for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { 675 if (hash == ctx->racy_stacks[i]) { 676 VPrintf(2, "ThreadSanitizer: suppressing report as doubled (stack)\n"); 677 return true; 678 } 679 } 680 return false; 681 } 682 683 static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) { 684 if (!flags()->suppress_equal_stacks) 685 return false; 686 RacyStacks hash; 687 hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); 688 hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); 689 { 690 ReadLock lock(&ctx->racy_mtx); 691 if (FindRacyStacks(hash)) 692 return true; 693 } 694 Lock lock(&ctx->racy_mtx); 695 if (FindRacyStacks(hash)) 696 return true; 697 ctx->racy_stacks.PushBack(hash); 698 return false; 699 } 700 701 static bool FindRacyAddress(const RacyAddress &ra0) { 702 for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { 703 RacyAddress ra2 = ctx->racy_addresses[i]; 704 uptr maxbeg = max(ra0.addr_min, ra2.addr_min); 705 uptr minend = min(ra0.addr_max, ra2.addr_max); 706 if (maxbeg < minend) { 707 VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n"); 708 return true; 709 } 710 } 711 return false; 712 } 713 714 static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) { 715 if (!flags()->suppress_equal_addresses) 716 return false; 717 RacyAddress ra0 = {addr_min, addr_max}; 718 { 719 ReadLock lock(&ctx->racy_mtx); 720 if (FindRacyAddress(ra0)) 721 return true; 722 } 723 Lock lock(&ctx->racy_mtx); 724 if (FindRacyAddress(ra0)) 725 return true; 726 ctx->racy_addresses.PushBack(ra0); 727 return false; 728 } 729 730 bool OutputReport(ThreadState *thr, const ScopedReport &srep) { 731 // These should have been checked in ShouldReport. 732 // It's too late to check them here, we have already taken locks. 733 CHECK(flags()->report_bugs); 734 CHECK(!thr->suppress_reports); 735 atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime()); 736 const ReportDesc *rep = srep.GetReport(); 737 CHECK_EQ(thr->current_report, nullptr); 738 thr->current_report = rep; 739 Suppression *supp = 0; 740 uptr pc_or_addr = 0; 741 for (uptr i = 0; pc_or_addr == 0 && i < rep->mops.Size(); i++) 742 pc_or_addr = IsSuppressed(rep->typ, rep->mops[i]->stack, &supp); 743 for (uptr i = 0; pc_or_addr == 0 && i < rep->stacks.Size(); i++) 744 pc_or_addr = IsSuppressed(rep->typ, rep->stacks[i], &supp); 745 for (uptr i = 0; pc_or_addr == 0 && i < rep->threads.Size(); i++) 746 pc_or_addr = IsSuppressed(rep->typ, rep->threads[i]->stack, &supp); 747 for (uptr i = 0; pc_or_addr == 0 && i < rep->locs.Size(); i++) 748 pc_or_addr = IsSuppressed(rep->typ, rep->locs[i], &supp); 749 if (pc_or_addr != 0) { 750 Lock lock(&ctx->fired_suppressions_mtx); 751 FiredSuppression s = {srep.GetReport()->typ, pc_or_addr, supp}; 752 ctx->fired_suppressions.push_back(s); 753 } 754 { 755 bool old_is_freeing = thr->is_freeing; 756 thr->is_freeing = false; 757 bool suppressed = OnReport(rep, pc_or_addr != 0); 758 thr->is_freeing = old_is_freeing; 759 if (suppressed) { 760 thr->current_report = nullptr; 761 return false; 762 } 763 } 764 PrintReport(rep); 765 __tsan_on_report(rep); 766 ctx->nreported++; 767 if (flags()->halt_on_error) 768 Die(); 769 thr->current_report = nullptr; 770 return true; 771 } 772 773 bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace) { 774 ReadLock lock(&ctx->fired_suppressions_mtx); 775 for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) { 776 if (ctx->fired_suppressions[k].type != type) 777 continue; 778 for (uptr j = 0; j < trace.size; j++) { 779 FiredSuppression *s = &ctx->fired_suppressions[k]; 780 if (trace.trace[j] == s->pc_or_addr) { 781 if (s->supp) 782 atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed); 783 return true; 784 } 785 } 786 } 787 return false; 788 } 789 790 static bool IsFiredSuppression(Context *ctx, ReportType type, uptr addr) { 791 ReadLock lock(&ctx->fired_suppressions_mtx); 792 for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) { 793 if (ctx->fired_suppressions[k].type != type) 794 continue; 795 FiredSuppression *s = &ctx->fired_suppressions[k]; 796 if (addr == s->pc_or_addr) { 797 if (s->supp) 798 atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed); 799 return true; 800 } 801 } 802 return false; 803 } 804 805 static bool RaceBetweenAtomicAndFree(ThreadState *thr) { 806 Shadow s0(thr->racy_state[0]); 807 Shadow s1(thr->racy_state[1]); 808 CHECK(!(s0.IsAtomic() && s1.IsAtomic())); 809 if (!s0.IsAtomic() && !s1.IsAtomic()) 810 return true; 811 if (s0.IsAtomic() && s1.IsFreed()) 812 return true; 813 if (s1.IsAtomic() && thr->is_freeing) 814 return true; 815 return false; 816 } 817 818 void ReportRace(ThreadState *thr) { 819 CheckedMutex::CheckNoLocks(); 820 821 // Symbolizer makes lots of intercepted calls. If we try to process them, 822 // at best it will cause deadlocks on internal mutexes. 823 ScopedIgnoreInterceptors ignore; 824 825 if (!ShouldReport(thr, ReportTypeRace)) 826 return; 827 if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr)) 828 return; 829 830 bool freed = false; 831 { 832 Shadow s(thr->racy_state[1]); 833 freed = s.GetFreedAndReset(); 834 thr->racy_state[1] = s.raw(); 835 } 836 837 uptr addr = ShadowToMem(thr->racy_shadow_addr); 838 uptr addr_min = 0; 839 uptr addr_max = 0; 840 { 841 uptr a0 = addr + Shadow(thr->racy_state[0]).addr0(); 842 uptr a1 = addr + Shadow(thr->racy_state[1]).addr0(); 843 uptr e0 = a0 + Shadow(thr->racy_state[0]).size(); 844 uptr e1 = a1 + Shadow(thr->racy_state[1]).size(); 845 addr_min = min(a0, a1); 846 addr_max = max(e0, e1); 847 if (IsExpectedReport(addr_min, addr_max - addr_min)) 848 return; 849 } 850 if (HandleRacyAddress(thr, addr_min, addr_max)) 851 return; 852 853 ReportType typ = ReportTypeRace; 854 if (thr->is_vptr_access && freed) 855 typ = ReportTypeVptrUseAfterFree; 856 else if (thr->is_vptr_access) 857 typ = ReportTypeVptrRace; 858 else if (freed) 859 typ = ReportTypeUseAfterFree; 860 861 if (IsFiredSuppression(ctx, typ, addr)) 862 return; 863 864 const uptr kMop = 2; 865 VarSizeStackTrace traces[kMop]; 866 uptr tags[kMop] = {kExternalTagNone}; 867 uptr toppc = TraceTopPC(thr); 868 if (toppc >> kEventPCBits) { 869 // This is a work-around for a known issue. 870 // The scenario where this happens is rather elaborate and requires 871 // an instrumented __sanitizer_report_error_summary callback and 872 // a __tsan_symbolize_external callback and a race during a range memory 873 // access larger than 8 bytes. MemoryAccessRange adds the current PC to 874 // the trace and starts processing memory accesses. A first memory access 875 // triggers a race, we report it and call the instrumented 876 // __sanitizer_report_error_summary, which adds more stuff to the trace 877 // since it is intrumented. Then a second memory access in MemoryAccessRange 878 // also triggers a race and we get here and call TraceTopPC to get the 879 // current PC, however now it contains some unrelated events from the 880 // callback. Most likely, TraceTopPC will now return a EventTypeFuncExit 881 // event. Later we subtract -1 from it (in GetPreviousInstructionPc) 882 // and the resulting PC has kExternalPCBit set, so we pass it to 883 // __tsan_symbolize_external_ex. __tsan_symbolize_external_ex is within its 884 // rights to crash since the PC is completely bogus. 885 // test/tsan/double_race.cpp contains a test case for this. 886 toppc = 0; 887 } 888 ObtainCurrentStack(thr, toppc, &traces[0], &tags[0]); 889 if (IsFiredSuppression(ctx, typ, traces[0])) 890 return; 891 892 // MutexSet is too large to live on stack. 893 Vector<u64> mset_buffer; 894 mset_buffer.Resize(sizeof(MutexSet) / sizeof(u64) + 1); 895 MutexSet *mset2 = new(&mset_buffer[0]) MutexSet(); 896 897 Shadow s2(thr->racy_state[1]); 898 RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2, &tags[1]); 899 if (IsFiredSuppression(ctx, typ, traces[1])) 900 return; 901 902 if (HandleRacyStacks(thr, traces)) 903 return; 904 905 // If any of the accesses has a tag, treat this as an "external" race. 906 uptr tag = kExternalTagNone; 907 for (uptr i = 0; i < kMop; i++) { 908 if (tags[i] != kExternalTagNone) { 909 typ = ReportTypeExternalRace; 910 tag = tags[i]; 911 break; 912 } 913 } 914 915 ThreadRegistryLock l0(&ctx->thread_registry); 916 ScopedReport rep(typ, tag); 917 for (uptr i = 0; i < kMop; i++) { 918 Shadow s(thr->racy_state[i]); 919 rep.AddMemoryAccess(addr, tags[i], s, traces[i], 920 i == 0 ? &thr->mset : mset2); 921 } 922 923 for (uptr i = 0; i < kMop; i++) { 924 FastState s(thr->racy_state[i]); 925 ThreadContext *tctx = static_cast<ThreadContext *>( 926 ctx->thread_registry.GetThreadLocked(s.tid())); 927 if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1) 928 continue; 929 rep.AddThread(tctx); 930 } 931 932 rep.AddLocation(addr_min, addr_max - addr_min); 933 934 #if !SANITIZER_GO 935 { 936 Shadow s(thr->racy_state[1]); 937 if (s.epoch() <= thr->last_sleep_clock.get(s.tid())) 938 rep.AddSleep(thr->last_sleep_stack_id); 939 } 940 #endif 941 942 OutputReport(thr, rep); 943 } 944 945 void PrintCurrentStack(ThreadState *thr, uptr pc) { 946 VarSizeStackTrace trace; 947 ObtainCurrentStack(thr, pc, &trace); 948 PrintStack(SymbolizeStack(trace)); 949 } 950 951 // Always inlining PrintCurrentStackSlow, because LocatePcInTrace assumes 952 // __sanitizer_print_stack_trace exists in the actual unwinded stack, but 953 // tail-call to PrintCurrentStackSlow breaks this assumption because 954 // __sanitizer_print_stack_trace disappears after tail-call. 955 // However, this solution is not reliable enough, please see dvyukov's comment 956 // http://reviews.llvm.org/D19148#406208 957 // Also see PR27280 comment 2 and 3 for breaking examples and analysis. 958 ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) { 959 #if !SANITIZER_GO 960 uptr bp = GET_CURRENT_FRAME(); 961 auto *ptrace = New<BufferedStackTrace>(); 962 ptrace->Unwind(pc, bp, nullptr, false); 963 964 for (uptr i = 0; i < ptrace->size / 2; i++) { 965 uptr tmp = ptrace->trace_buffer[i]; 966 ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1]; 967 ptrace->trace_buffer[ptrace->size - i - 1] = tmp; 968 } 969 PrintStack(SymbolizeStack(*ptrace)); 970 #endif 971 } 972 973 } // namespace __tsan 974 975 using namespace __tsan; 976 977 extern "C" { 978 SANITIZER_INTERFACE_ATTRIBUTE 979 void __sanitizer_print_stack_trace() { 980 PrintCurrentStackSlow(StackTrace::GetCurrentPc()); 981 } 982 } // extern "C" 983