tsan_report.cc revision 67a64dd8259fdbd867633b27f54d584f435f1ce6
1//===-- tsan_report.cc ----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of ThreadSanitizer (TSan), a race detector. 11// 12//===----------------------------------------------------------------------===// 13#include "tsan_report.h" 14#include "tsan_platform.h" 15#include "tsan_rtl.h" 16 17namespace __tsan { 18 19ReportDesc::ReportDesc() 20 : stacks(MBlockReportStack) 21 , mops(MBlockReportMop) 22 , locs(MBlockReportLoc) 23 , mutexes(MBlockReportMutex) 24 , threads(MBlockReportThread) { 25} 26 27ReportDesc::~ReportDesc() { 28} 29 30static void PrintHeader(ReportType typ) { 31 TsanPrintf("WARNING: ThreadSanitizer: "); 32 33 if (typ == ReportTypeRace) 34 TsanPrintf("data race"); 35 else if (typ == ReportTypeUseAfterFree) 36 TsanPrintf("heap-use-after-free"); 37 else if (typ == ReportTypeThreadLeak) 38 TsanPrintf("thread leak"); 39 else if (typ == ReportTypeMutexDestroyLocked) 40 TsanPrintf("destroy of a locked mutex"); 41 else if (typ == ReportTypeSignalUnsafe) 42 TsanPrintf("signal-unsafe call inside of a signal"); 43 44 TsanPrintf(" (pid=%d)\n", GetPid()); 45} 46 47static void PrintStack(const ReportStack *ent) { 48 for (int i = 0; ent; ent = ent->next, i++) { 49 TsanPrintf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line); 50 if (ent->col) 51 TsanPrintf(":%d", ent->col); 52 if (ent->module && ent->offset) 53 TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset); 54 else 55 TsanPrintf(" (%p)\n", (void*)ent->pc); 56 } 57} 58 59static void PrintMop(const ReportMop *mop, bool first) { 60 TsanPrintf(" %s of size %d at %p", 61 (first ? (mop->write ? "Write" : "Read") 62 : (mop->write ? "Previous write" : "Previous read")), 63 mop->size, (void*)mop->addr); 64 if (mop->tid == 0) 65 TsanPrintf(" by main thread:\n"); 66 else 67 TsanPrintf(" by thread %d:\n", mop->tid); 68 PrintStack(mop->stack); 69} 70 71static void PrintLocation(const ReportLocation *loc) { 72 if (loc->type == ReportLocationGlobal) { 73 TsanPrintf(" Location is global '%s' of size %lu at %lx %s:%d\n", 74 loc->name, loc->size, loc->addr, loc->file, loc->line); 75 } else if (loc->type == ReportLocationHeap) { 76 TsanPrintf(" Location is heap of size %lu at %lx allocated " 77 "by thread %d:\n", loc->size, loc->addr, loc->tid); 78 PrintStack(loc->stack); 79 } else if (loc->type == ReportLocationStack) { 80 TsanPrintf(" Location is stack of thread %d:\n", loc->tid); 81 } 82} 83 84static void PrintMutex(const ReportMutex *rm) { 85 if (rm->stack == 0) 86 return; 87 TsanPrintf(" Mutex %d created at:\n", rm->id); 88 PrintStack(rm->stack); 89} 90 91static void PrintThread(const ReportThread *rt) { 92 if (rt->id == 0) // Little sense in describing the main thread. 93 return; 94 TsanPrintf(" Thread %d", rt->id); 95 if (rt->name) 96 TsanPrintf(" '%s'", rt->name); 97 TsanPrintf(" (%s)", rt->running ? "running" : "finished"); 98 if (rt->stack) 99 TsanPrintf(" created at:"); 100 TsanPrintf("\n"); 101 PrintStack(rt->stack); 102} 103 104void PrintReport(const ReportDesc *rep) { 105 TsanPrintf("==================\n"); 106 PrintHeader(rep->typ); 107 108 for (uptr i = 0; i < rep->stacks.Size(); i++) 109 PrintStack(rep->stacks[i]); 110 111 for (uptr i = 0; i < rep->mops.Size(); i++) 112 PrintMop(rep->mops[i], i == 0); 113 114 for (uptr i = 0; i < rep->locs.Size(); i++) 115 PrintLocation(rep->locs[i]); 116 117 for (uptr i = 0; i < rep->mutexes.Size(); i++) 118 PrintMutex(rep->mutexes[i]); 119 120 for (uptr i = 0; i < rep->threads.Size(); i++) 121 PrintThread(rep->threads[i]); 122 123 TsanPrintf("==================\n"); 124} 125 126} // namespace __tsan 127