tsan_report.cc revision 0ab628c61594eb80612e5389d9c33da0e0d70c66
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) 24848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov , threads(MBlockReportThread) 25848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov , sleep() { 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 287ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::~ReportDesc() { 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 31c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#ifndef TSAN_GO 32c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintHeader(ReportType typ) { 3467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("WARNING: ThreadSanitizer: "); 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == ReportTypeRace) 3767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("data race"); 38069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov else if (typ == ReportTypeUseAfterFree) 3967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("heap-use-after-free"); 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeThreadLeak) 4167a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("thread leak"); 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeMutexDestroyLocked) 4367a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("destroy of a locked mutex"); 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else if (typ == ReportTypeSignalUnsafe) 4567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("signal-unsafe call inside of a signal"); 467a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov else if (typ == ReportTypeErrnoInSignal) 477a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov TsanPrintf("signal handler spoils errno"); 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (pid=%d)\n", GetPid()); 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 521da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukovvoid PrintStack(const ReportStack *ent) { 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; ent; ent = ent->next, i++) { 5467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line); 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->col) 5667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(":%d", ent->col); 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->module && ent->offset) 5867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset); 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 6067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%p)\n", (void*)ent->pc); 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 62ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf("\n"); 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) { 6667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" %s of size %d at %p", 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (first ? (mop->write ? "Write" : "Read") 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : (mop->write ? "Previous write" : "Previous read")), 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany mop->size, (void*)mop->addr); 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (mop->tid == 0) 7167a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" by main thread:\n"); 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 7367a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" by thread %d:\n", mop->tid); 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(mop->stack); 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) { 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (loc->type == ReportLocationGlobal) { 79e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov TsanPrintf(" Location is global '%s' of size %zu at %zx %s:%d\n", 8067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov loc->name, loc->size, loc->addr, loc->file, loc->line); 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationHeap) { 82ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" Location is heap block of size %zu at %p allocated", 83ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov loc->size, loc->addr); 84ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov if (loc->tid == 0) 85ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" by main thread:\n"); 86ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov else 87ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov TsanPrintf(" by thread %d:\n", loc->tid); 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(loc->stack); 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationStack) { 9067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Location is stack of thread %d:\n", loc->tid); 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) { 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rm->stack == 0) 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 9767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Mutex %d created at:\n", rm->id); 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rm->stack); 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) { 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->id == 0) // Little sense in describing the main thread. 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 10467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" Thread %d", rt->id); 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->name) 10667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" '%s'", rt->name); 10767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" (%s)", rt->running ? "running" : "finished"); 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->stack) 10967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf(" created at:"); 11067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("\n"); 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rt->stack); 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 114848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovstatic void PrintSleep(const ReportStack *s) { 115848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov TsanPrintf(" As if synchronized via sleep:\n"); 116848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintStack(s); 117848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 118848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) { 12067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("==================\n"); 1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintHeader(rep->typ); 1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 123332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov for (uptr i = 0; i < rep->stacks.Size(); i++) { 124332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov if (i) 125332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov TsanPrintf(" and:\n"); 1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rep->stacks[i]); 127332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov } 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mops.Size(); i++) 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMop(rep->mops[i], i == 0); 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 132848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (rep->sleep) 133848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintSleep(rep->sleep); 134848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->locs.Size(); i++) 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintLocation(rep->locs[i]); 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mutexes.Size(); i++) 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMutex(rep->mutexes[i]); 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->threads.Size(); i++) 1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintThread(rep->threads[i]); 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("==================\n"); 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 147c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#else 148c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 1490ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukovvoid PrintStack(const ReportStack *ent) { 150c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (int i = 0; ent; ent = ent->next, i++) { 151853733e772b2885d93fdf994dedc4a1b5dc1369eDmitry Vyukov TsanPrintf(" %s()\n %s:%d +0x%zx\n", 152853733e772b2885d93fdf994dedc4a1b5dc1369eDmitry Vyukov ent->func, ent->file, ent->line, (void*)ent->offset); 153c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov } 154bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov TsanPrintf("\n"); 155c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 156c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 157c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovstatic void PrintMop(const ReportMop *mop, bool first) { 158c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("%s by goroutine %d:\n", 159c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov (first ? (mop->write ? "Write" : "Read") 160c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov : (mop->write ? "Previous write" : "Previous read")), 161c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov mop->tid); 162c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintStack(mop->stack); 163c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 164c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 16543046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukovstatic void PrintThread(const ReportThread *rt) { 16643046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov if (rt->id == 0) // Little sense in describing the main thread. 16743046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov return; 16843046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov TsanPrintf("Goroutine %d (%s) created at:\n", 16943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov rt->id, rt->running ? "running" : "finished"); 17043046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintStack(rt->stack); 17143046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov} 17243046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov 173c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovvoid PrintReport(const ReportDesc *rep) { 174c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("==================\n"); 175bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov TsanPrintf("WARNING: DATA RACE\n"); 176c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (uptr i = 0; i < rep->mops.Size(); i++) 177c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintMop(rep->mops[i], i == 0); 17843046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov for (uptr i = 0; i < rep->threads.Size(); i++) 17943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintThread(rep->threads[i]); 180c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov TsanPrintf("==================\n"); 181c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 182c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 183c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#endif 184c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 186