tsan_report.cc revision ff35f1d82b4f145b3477ef27a7a2e7b63c486988
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_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#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 30c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#ifndef TSAN_GO 31c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintHeader(ReportType typ) { 3367a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("WARNING: ThreadSanitizer: "); 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == ReportTypeRace) 3667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("data race"); 37069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov else if (typ == ReportTypeUseAfterFree) 3867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("heap-use-after-free"); 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeThreadLeak) 4067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("thread leak"); 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeMutexDestroyLocked) 4267a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("destroy of a locked mutex"); 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeSignalUnsafe) 4467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("signal-unsafe call inside of a signal"); 457a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov else if (typ == ReportTypeErrnoInSignal) 467a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov TsanPrintf("signal handler spoils errno"); 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (pid=%d)\n", GetPid()); 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintStack(const ReportStack *ent) { 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; ent; ent = ent->next, i++) { 5367a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line); 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->col) 5567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(":%d", ent->col); 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->module && ent->offset) 5767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset); 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 5967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%p)\n", (void*)ent->pc); 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 61ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf("\n"); 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) { 6567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" %s of size %d at %p", 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (first ? (mop->write ? "Write" : "Read") 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : (mop->write ? "Previous write" : "Previous read")), 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->size, (void*)mop->addr); 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (mop->tid == 0) 7067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" by main thread:\n"); 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 7267a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" by thread %d:\n", mop->tid); 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(mop->stack); 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) { 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (loc->type == ReportLocationGlobal) { 78e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov TsanPrintf(" Location is global '%s' of size %zu at %zx %s:%d\n", 7967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov loc->name, loc->size, loc->addr, loc->file, loc->line); 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationHeap) { 81ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" Location is heap block of size %zu at %p allocated", 82ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->size, loc->addr); 83ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (loc->tid == 0) 84ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" by main thread:\n"); 85ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov else 86ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" by thread %d:\n", loc->tid); 877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(loc->stack); 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationStack) { 8967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Location is stack of thread %d:\n", loc->tid); 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) { 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rm->stack == 0) 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 9667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Mutex %d created at:\n", rm->id); 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rm->stack); 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) { 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->id == 0) // Little sense in describing the main thread. 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 10367a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Thread %d", rt->id); 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->name) 10567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" '%s'", rt->name); 10667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%s)", rt->running ? "running" : "finished"); 1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->stack) 10867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" created at:"); 10967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("\n"); 1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rt->stack); 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) { 11467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("==================\n"); 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintHeader(rep->typ); 1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 117332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov for (uptr i = 0; i < rep->stacks.Size(); i++) { 118332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov if (i) 119332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov TsanPrintf(" and:\n"); 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rep->stacks[i]); 121332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov } 1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mops.Size(); i++) 1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMop(rep->mops[i], i == 0); 1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->locs.Size(); i++) 1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintLocation(rep->locs[i]); 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mutexes.Size(); i++) 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMutex(rep->mutexes[i]); 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->threads.Size(); i++) 1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintThread(rep->threads[i]); 1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("==================\n"); 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 138c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#else 139c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 140c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovstatic void PrintStack(const ReportStack *ent) { 141c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (int i = 0; ent; ent = ent->next, i++) { 142853733e772b2885d93fdf994dedc4a1b5dc1369eDmitry Vyukov TsanPrintf(" %s()\n %s:%d +0x%zx\n", 143853733e772b2885d93fdf994dedc4a1b5dc1369eDmitry Vyukov ent->func, ent->file, ent->line, (void*)ent->offset); 144c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov } 145bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov TsanPrintf("\n"); 146c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 147c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 148c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovstatic void PrintMop(const ReportMop *mop, bool first) { 149c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("%s by goroutine %d:\n", 150c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov (first ? (mop->write ? "Write" : "Read") 151c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov : (mop->write ? "Previous write" : "Previous read")), 152c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov mop->tid); 153c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintStack(mop->stack); 154c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 155c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 15643046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukovstatic void PrintThread(const ReportThread *rt) { 15743046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov if (rt->id == 0) // Little sense in describing the main thread. 15843046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov return; 15943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov TsanPrintf("Goroutine %d (%s) created at:\n", 16043046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov rt->id, rt->running ? "running" : "finished"); 16143046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintStack(rt->stack); 16243046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov} 16343046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov 164c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovvoid PrintReport(const ReportDesc *rep) { 165c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("==================\n"); 166bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov TsanPrintf("WARNING: DATA RACE\n"); 167c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (uptr i = 0; i < rep->mops.Size(); i++) 168c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintMop(rep->mops[i], i == 0); 16943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov for (uptr i = 0; i < rep->threads.Size(); i++) 17043046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintThread(rep->threads[i]); 171c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("==================\n"); 172c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 173c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 174c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#endif 175c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 177