tsan_report.cc revision 069ce828e3057819ee34426496ea7080f7cc52f0
17ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===-- tsan_report.cc ------------------------------------------*- C++ -*-===// 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#include "tsan_report.h" 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 197ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::ReportDesc() 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : stacks(MBlockReportStack) 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mops(MBlockReportMop) 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , locs(MBlockReportLoc) 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mutexes(MBlockReportMutex) 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , threads(MBlockReportThread) { 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 277ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::~ReportDesc() { 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintHeader(ReportType typ) { 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("WARNING: ThreadSanitizer: "); 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == ReportTypeRace) 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("data race"); 35069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov else if (typ == ReportTypeUseAfterFree) 36069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Printf("heap-use-after-free"); 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeThreadLeak) 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("thread leak"); 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeMutexDestroyLocked) 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("destroy of a locked mutex"); 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeSignalUnsafe) 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("signal-unsafe call inside of a signal"); 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" (pid=%d)\n", GetPid()); 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintStack(const ReportStack *ent) { 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; ent; ent = ent->next, i++) { 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line); 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->col) 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(":%d", ent->col); 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->module && ent->offset) 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" (%s+%p)\n", ent->module, (void*)ent->offset); 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" (%p)\n", (void*)ent->pc); 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) { 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" %s of size %d at %p", 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (first ? (mop->write ? "Write" : "Read") 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : (mop->write ? "Previous write" : "Previous read")), 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->size, (void*)mop->addr); 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (mop->tid == 0) 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" by main thread:\n"); 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" by thread %d:\n", mop->tid); 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(mop->stack); 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) { 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (loc->type == ReportLocationGlobal) { 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" Location is global '%s' of size %lu at %lx %s:%d\n", 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->name, loc->size, loc->addr, loc->file, loc->line); 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationHeap) { 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" Location is heap of size %lu at %lx allocated by thread %d:\n", 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany loc->size, loc->addr, loc->tid); 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(loc->stack); 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationStack) { 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" Location is stack of thread %d:\n", loc->tid); 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) { 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rm->stack == 0) 867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" Mutex %d created at:\n", rm->id); 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rm->stack); 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) { 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->id == 0) // Little sense in describing the main thread. 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" Thread %d", rt->id); 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->name) 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" '%s'", rt->name); 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" (%s)", rt->running ? "running" : "finished"); 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->stack) 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf(" created at:"); 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("\n"); 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rt->stack); 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) { 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("==================\n"); 1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintHeader(rep->typ); 1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->stacks.Size(); i++) 1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rep->stacks[i]); 1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mops.Size(); i++) 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMop(rep->mops[i], i == 0); 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->locs.Size(); i++) 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintLocation(rep->locs[i]); 1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mutexes.Size(); i++) 1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMutex(rep->mutexes[i]); 1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->threads.Size(); i++) 1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintThread(rep->threads[i]); 1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Printf("==================\n"); 1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 127