tsan_report.cc revision a27512c4e115df4f260501a94b8d343f9ed955af
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" 16a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany#include "sanitizer_common/sanitizer_report_decorator.h" 177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 20a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryanyclass Decorator: private __sanitizer::AnsiColorDecorator { 21a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany public: 22a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { } 23a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Warning() { return Red(); } 24a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndWarning() { return Default(); } 25a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Access() { return Blue(); } 26a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndAccess() { return Default(); } 27a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *ThreadDescription() { return Cyan(); } 28a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndThreadDescription() { return Default(); } 29a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Location() { return Green(); } 30a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndLocation() { return Default(); } 31a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Sleep() { return Yellow(); } 32a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndSleep() { return Default(); } 33a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Mutex() { return Magenta(); } 34a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndMutex() { return Default(); } 35a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany}; 36a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany 377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::ReportDesc() 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : stacks(MBlockReportStack) 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mops(MBlockReportMop) 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , locs(MBlockReportLoc) 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mutexes(MBlockReportMutex) 42848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov , threads(MBlockReportThread) 434536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov , sleep() 444536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov , count() { 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 47ad9da372f962495b3487685232d09390be841b1cDmitry VyukovReportMop::ReportMop() 48ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov : mset(MBlockReportMutex) { 49ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 50ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 517ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::~ReportDesc() { 52aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov // FIXME(dvyukov): it must be leaking a lot of memory. 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 55c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#ifndef TSAN_GO 56c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 57da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukovconst int kThreadBufSize = 32; 58da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukovconst char *thread_name(char *buf, int tid) { 59da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov if (tid == 0) 60da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov return "main thread"; 61da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov internal_snprintf(buf, kThreadBufSize, "thread T%d", tid); 62da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov return buf; 63da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov} 64da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov 652f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryanystatic const char *ReportTypeString(ReportType typ) { 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == ReportTypeRace) 672f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "data race"; 680dc47b652dfbe0d61d153eded02bae9487a7b539Dmitry Vyukov if (typ == ReportTypeVptrRace) 690dc47b652dfbe0d61d153eded02bae9487a7b539Dmitry Vyukov return "data race on vptr (ctor/dtor vs virtual call)"; 702f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeUseAfterFree) 712f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "heap-use-after-free"; 722f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeThreadLeak) 732f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "thread leak"; 742f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeMutexDestroyLocked) 752f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "destroy of a locked mutex"; 762f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeSignalUnsafe) 772f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "signal-unsafe call inside of a signal"; 782f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeErrnoInSignal) 792f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "signal handler spoils errno"; 802f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return ""; 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 831da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukovvoid PrintStack(const ReportStack *ent) { 84dc2a27ecd65079f1916f5ab53ec646f9a9e61349Dmitry Vyukov if (ent == 0) { 8595f50b126cebecc0165fbf6e4c8209c640836271Dmitry Vyukov Printf(" [failed to restore the stack]\n\n"); 86dc2a27ecd65079f1916f5ab53ec646f9a9e61349Dmitry Vyukov return; 87dc2a27ecd65079f1916f5ab53ec646f9a9e61349Dmitry Vyukov } 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; ent; ent = ent->next, i++) { 89b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line); 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->col) 91b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(":%d", ent->col); 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ent->module && ent->offset) 93b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" (%s+%p)\n", ent->module, (void*)ent->offset); 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 95b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" (%p)\n", (void*)ent->pc); 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 97b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 100ad9da372f962495b3487685232d09390be841b1cDmitry Vyukovstatic void PrintMutexSet(Vector<ReportMopMutex> const& mset) { 101ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov for (uptr i = 0; i < mset.Size(); i++) { 102ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (i == 0) 103ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" (mutexes:"); 104ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov const ReportMopMutex m = mset[i]; 105ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" %s M%llu", m.write ? "write" : "read", m.id); 106ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(i == mset.Size() - 1 ? ")" : ","); 107ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } 108ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 109ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 1100a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukovstatic const char *MopDesc(bool first, bool write, bool atomic) { 1110a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov return atomic ? (first ? (write ? "Atomic write" : "Atomic read") 1120a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (write ? "Previous atomic write" : "Previous atomic read")) 1130a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (first ? (write ? "Write" : "Read") 1140a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (write ? "Previous write" : "Previous read")); 1150a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov} 1160a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov 1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) { 118a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 119da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 120a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Access()); 121da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" %s of size %d at %p by %s", 1220a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov MopDesc(first, mop->write, mop->atomic), 123da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov mop->size, (void*)mop->addr, 124da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov thread_name(thrbuf, mop->tid)); 125ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov PrintMutexSet(mop->mset); 126ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(":\n"); 127a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndAccess()); 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(mop->stack); 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) { 132a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 133c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov char thrbuf[kThreadBufSize]; 134a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany bool print_stack = false; 135a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Location()); 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (loc->type == ReportLocationGlobal) { 1375a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov Printf(" Location is global '%s' of size %zu at %zx (%s+%p)\n\n", 1385a1f23310cc4a1debae8741653defe620518e612Dmitry Vyukov loc->name, loc->size, loc->addr, loc->module, loc->offset); 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationHeap) { 140da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 141da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" Location is heap block of size %zu at %p allocated by %s:\n", 142da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov loc->size, loc->addr, thread_name(thrbuf, loc->tid)); 143a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany print_stack = true; 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationStack) { 145fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov Printf(" Location is stack of %s.\n\n", thread_name(thrbuf, loc->tid)); 146fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov } else if (loc->type == ReportLocationTLS) { 147fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov Printf(" Location is TLS of %s.\n\n", thread_name(thrbuf, loc->tid)); 148c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov } else if (loc->type == ReportLocationFD) { 149c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov Printf(" Location is file descriptor %d created by %s at:\n", 150c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov loc->fd, thread_name(thrbuf, loc->tid)); 151a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany print_stack = true; 1527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 153a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndLocation()); 154a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany if (print_stack) 155a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany PrintStack(loc->stack); 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) { 159a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 160ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (rm->destroyed) { 161a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Mutex()); 162ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" Mutex M%llu is already destroyed.\n\n", rm->id); 163a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndMutex()); 164ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } else { 165a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Mutex()); 166ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" Mutex M%llu created at:\n", rm->id); 167a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndMutex()); 168ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov PrintStack(rm->stack); 169ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } 1707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) { 173a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->id == 0) // Little sense in describing the main thread. 1757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 176a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.ThreadDescription()); 177ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" Thread T%d", rt->id); 1782bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov if (rt->name && rt->name[0] != '\0') 179b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" '%s'", rt->name); 180da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 181da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" (tid=%zu, %s) created by %s", 182da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov rt->pid, rt->running ? "running" : "finished", 183da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov thread_name(thrbuf, rt->parent_tid)); 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->stack) 185da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" at:"); 186b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 187a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndThreadDescription()); 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rt->stack); 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 191848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovstatic void PrintSleep(const ReportStack *s) { 192a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 193a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Sleep()); 194b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" As if synchronized via sleep:\n"); 195a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndSleep()); 196848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintStack(s); 197848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 198848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 1992f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryanystatic ReportStack *ChooseSummaryStack(const ReportDesc *rep) { 2002f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->mops.Size()) 2012f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->mops[0]->stack; 2022f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->stacks.Size()) 2032f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->stacks[0]; 2042f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->mutexes.Size()) 2052f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->mutexes[0]->stack; 2062f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->threads.Size()) 2072f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->threads[0]->stack; 2082f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return 0; 2092f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany} 2102f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 2115ba301dfe9a39c02b3faeb0fa252473f1d6e742cAlexey SamsonovReportStack *SkipTsanInternalFrames(ReportStack *ent) { 2125ba301dfe9a39c02b3faeb0fa252473f1d6e742cAlexey Samsonov while (FrameIsInternal(ent) && ent->next) 2135ba301dfe9a39c02b3faeb0fa252473f1d6e742cAlexey Samsonov ent = ent->next; 2142f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return ent; 2152f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany} 2162f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) { 218a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 219b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 2202f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany const char *rep_typ_str = ReportTypeString(rep->typ); 221a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Warning()); 2220b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str, 2230b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne (int)internal_getpid()); 224a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndWarning()); 2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 226332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov for (uptr i = 0; i < rep->stacks.Size(); i++) { 227332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov if (i) 228b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" and:\n"); 2297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rep->stacks[i]); 230332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov } 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mops.Size(); i++) 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMop(rep->mops[i], i == 0); 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 235848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (rep->sleep) 236848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintSleep(rep->sleep); 237848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->locs.Size(); i++) 2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintLocation(rep->locs[i]); 2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mutexes.Size(); i++) 2427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMutex(rep->mutexes[i]); 2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->threads.Size(); i++) 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintThread(rep->threads[i]); 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2474536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov if (rep->typ == ReportTypeThreadLeak && rep->count > 1) 2484536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov Printf(" And %d more similar thread leaks.\n\n", rep->count - 1); 2494536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov 2505ba301dfe9a39c02b3faeb0fa252473f1d6e742cAlexey Samsonov if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep))) 2512f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func); 2522f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 253b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2569d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov#else // #ifndef TSAN_GO 2579d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov 2589d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukovconst int kMainThreadId = 1; 259c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 2600ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukovvoid PrintStack(const ReportStack *ent) { 2616c0fbcae2f03eb78f82969bea61ccdbd2fb58e27Dmitry Vyukov if (ent == 0) { 2629d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf(" [failed to restore the stack]\n"); 2636c0fbcae2f03eb78f82969bea61ccdbd2fb58e27Dmitry Vyukov return; 2646c0fbcae2f03eb78f82969bea61ccdbd2fb58e27Dmitry Vyukov } 265c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (int i = 0; ent; ent = ent->next, i++) { 266b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" %s()\n %s:%d +0x%zx\n", 267853733e772b2885d93fdf994dedc4a1b5dc1369eDmitry Vyukov ent->func, ent->file, ent->line, (void*)ent->offset); 268c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov } 269c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 270c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 271c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovstatic void PrintMop(const ReportMop *mop, bool first) { 2729d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("\n"); 2739d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("%s by ", 274c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov (first ? (mop->write ? "Write" : "Read") 2759d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov : (mop->write ? "Previous write" : "Previous read"))); 2769d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov if (mop->tid == kMainThreadId) 2779d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("main goroutine:\n"); 2789d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov else 2799d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("goroutine %d:\n", mop->tid); 280c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintStack(mop->stack); 281c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 282c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 28343046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukovstatic void PrintThread(const ReportThread *rt) { 2849d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov if (rt->id == kMainThreadId) 28543046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov return; 2869d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("\n"); 287b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Goroutine %d (%s) created at:\n", 28843046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov rt->id, rt->running ? "running" : "finished"); 28943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintStack(rt->stack); 29043046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov} 29143046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov 292c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovvoid PrintReport(const ReportDesc *rep) { 293b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 2949d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("WARNING: DATA RACE"); 295c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov for (uptr i = 0; i < rep->mops.Size(); i++) 296c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintMop(rep->mops[i], i == 0); 29743046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov for (uptr i = 0; i < rep->threads.Size(); i++) 29843046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintThread(rep->threads[i]); 299b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 300c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 301c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 302c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#endif 303c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 3047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 305