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" 166d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_common/sanitizer_placement_new.h" 17a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany#include "sanitizer_common/sanitizer_report_decorator.h" 186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_common/sanitizer_stacktrace_printer.h" 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2286277eb844c4983c81de62d7c050e92fe7155788Stephen HinesReportStack::ReportStack() : frames(nullptr), suppressable(false) {} 236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 2486277eb844c4983c81de62d7c050e92fe7155788Stephen HinesReportStack *ReportStack::New() { 256d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack)); 2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return new(mem) ReportStack(); 276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 296d1862363c88c183b0ed7740fca876342cf0474bStephen HinesReportLocation::ReportLocation(ReportLocationType type) 306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines : type(type), global(), heap_chunk_start(0), heap_chunk_size(0), tid(0), 316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines fd(0), suppressable(false), stack(nullptr) {} 326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 336d1862363c88c183b0ed7740fca876342cf0474bStephen HinesReportLocation *ReportLocation::New(ReportLocationType type) { 346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *mem = internal_alloc(MBlockReportStack, sizeof(ReportLocation)); 356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return new(mem) ReportLocation(type); 366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 386a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesclass Decorator: public __sanitizer::SanitizerCommonDecorator { 39a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany public: 406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines Decorator() : SanitizerCommonDecorator() { } 41a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Warning() { return Red(); } 42a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndWarning() { return Default(); } 43a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Access() { return Blue(); } 44a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndAccess() { return Default(); } 45a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *ThreadDescription() { return Cyan(); } 46a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndThreadDescription() { return Default(); } 47a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Location() { return Green(); } 48a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndLocation() { return Default(); } 49a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Sleep() { return Yellow(); } 50a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndSleep() { return Default(); } 51a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *Mutex() { return Magenta(); } 52a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany const char *EndMutex() { return Default(); } 53a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany}; 54a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany 557ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::ReportDesc() 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : stacks(MBlockReportStack) 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mops(MBlockReportMop) 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , locs(MBlockReportLoc) 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , mutexes(MBlockReportMutex) 60848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov , threads(MBlockReportThread) 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines , unique_tids(MBlockReportThread) 624536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov , sleep() 634536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov , count() { 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 66ad9da372f962495b3487685232d09390be841b1cDmitry VyukovReportMop::ReportMop() 67ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov : mset(MBlockReportMutex) { 68ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 69ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 707ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyReportDesc::~ReportDesc() { 71aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov // FIXME(dvyukov): it must be leaking a lot of memory. 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO 75c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 76da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukovconst int kThreadBufSize = 32; 77da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukovconst char *thread_name(char *buf, int tid) { 78da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov if (tid == 0) 79da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov return "main thread"; 80da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov internal_snprintf(buf, kThreadBufSize, "thread T%d", tid); 81da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov return buf; 82da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov} 83da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov 842f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryanystatic const char *ReportTypeString(ReportType typ) { 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (typ == ReportTypeRace) 862f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "data race"; 870dc47b652dfbe0d61d153eded02bae9487a7b539Dmitry Vyukov if (typ == ReportTypeVptrRace) 880dc47b652dfbe0d61d153eded02bae9487a7b539Dmitry Vyukov return "data race on vptr (ctor/dtor vs virtual call)"; 892f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeUseAfterFree) 902f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "heap-use-after-free"; 916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (typ == ReportTypeVptrUseAfterFree) 926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return "heap-use-after-free (virtual call vs free)"; 932f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeThreadLeak) 942f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "thread leak"; 952f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeMutexDestroyLocked) 962f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "destroy of a locked mutex"; 972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (typ == ReportTypeMutexDoubleLock) 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return "double lock of a mutex"; 99c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (typ == ReportTypeMutexInvalidAccess) 100c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return "use of an invalid mutex (e.g. uninitialized or destroyed)"; 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (typ == ReportTypeMutexBadUnlock) 1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return "unlock of an unlocked mutex (or by a wrong thread)"; 1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (typ == ReportTypeMutexBadReadLock) 1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return "read lock of a write locked mutex"; 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (typ == ReportTypeMutexBadReadUnlock) 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return "read unlock of a write locked mutex"; 1072f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeSignalUnsafe) 1082f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "signal-unsafe call inside of a signal"; 1092f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (typ == ReportTypeErrnoInSignal) 1102f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return "signal handler spoils errno"; 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (typ == ReportTypeDeadlock) 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return "lock-order-inversion (potential deadlock)"; 1132f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return ""; 1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 116799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_MAC 117799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic const char *const kInterposedFunctionPrefix = "wrap_"; 118799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else 119799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic const char *const kInterposedFunctionPrefix = "__interceptor_"; 120799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 1221da1056127d1dbcacdd035eb4149257848f7c4dfDmitry Vyukovvoid PrintStack(const ReportStack *ent) { 12386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (ent == 0 || ent->frames == 0) { 12495f50b126cebecc0165fbf6e4c8209c640836271Dmitry Vyukov Printf(" [failed to restore the stack]\n\n"); 125dc2a27ecd65079f1916f5ab53ec646f9a9e61349Dmitry Vyukov return; 126dc2a27ecd65079f1916f5ab53ec646f9a9e61349Dmitry Vyukov } 12786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SymbolizedStack *frame = ent->frames; 12886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { 1296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines InternalScopedString res(2 * GetPageSizeCached()); 13086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, 131cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar common_flags()->symbolize_vs_style, 132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar common_flags()->strip_path_prefix, kInterposedFunctionPrefix); 1336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Printf("%s\n", res.data()); 1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 135b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 138ad9da372f962495b3487685232d09390be841b1cDmitry Vyukovstatic void PrintMutexSet(Vector<ReportMopMutex> const& mset) { 139ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov for (uptr i = 0; i < mset.Size(); i++) { 140ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (i == 0) 141ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" (mutexes:"); 142ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov const ReportMopMutex m = mset[i]; 143ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" %s M%llu", m.write ? "write" : "read", m.id); 144ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(i == mset.Size() - 1 ? ")" : ","); 145ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } 146ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 147ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 1480a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukovstatic const char *MopDesc(bool first, bool write, bool atomic) { 1490a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov return atomic ? (first ? (write ? "Atomic write" : "Atomic read") 1500a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (write ? "Previous atomic write" : "Previous atomic read")) 1510a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (first ? (write ? "Write" : "Read") 1520a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov : (write ? "Previous write" : "Previous read")); 1530a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov} 1540a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) { 156a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 157da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 158a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Access()); 159da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" %s of size %d at %p by %s", 1600a07b354fe95d50911c620b42fc031868ef15cc1Dmitry Vyukov MopDesc(first, mop->write, mop->atomic), 161da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov mop->size, (void*)mop->addr, 162da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov thread_name(thrbuf, mop->tid)); 163ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov PrintMutexSet(mop->mset); 164ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(":\n"); 165a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndAccess()); 1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(mop->stack); 1677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) { 170a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 171c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov char thrbuf[kThreadBufSize]; 172a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany bool print_stack = false; 173a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Location()); 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (loc->type == ReportLocationGlobal) { 1756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines const DataInfo &global = loc->global; 176799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (global.size != 0) 177799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n", 178799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar global.name, global.size, global.start, 179799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar StripModuleName(global.module), global.module_offset); 180799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar else 181799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf(" Location is global '%s' at %p (%s+%p)\n\n", global.name, 182799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar global.start, StripModuleName(global.module), 183799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar global.module_offset); 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationHeap) { 185da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 186da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" Location is heap block of size %zu at %p allocated by %s:\n", 1876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines loc->heap_chunk_size, loc->heap_chunk_start, 1886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines thread_name(thrbuf, loc->tid)); 189a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany print_stack = true; 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (loc->type == ReportLocationStack) { 191fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov Printf(" Location is stack of %s.\n\n", thread_name(thrbuf, loc->tid)); 192fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov } else if (loc->type == ReportLocationTLS) { 193fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov Printf(" Location is TLS of %s.\n\n", thread_name(thrbuf, loc->tid)); 194c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov } else if (loc->type == ReportLocationFD) { 195c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov Printf(" Location is file descriptor %d created by %s at:\n", 196c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov loc->fd, thread_name(thrbuf, loc->tid)); 197a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany print_stack = true; 1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 199a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndLocation()); 200a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany if (print_stack) 201a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany PrintStack(loc->stack); 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void PrintMutexShort(const ReportMutex *rm, const char *after) { 2052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Decorator d; 2062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.EndMutex(), after); 2072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void PrintMutexShortWithAddress(const ReportMutex *rm, 2102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const char *after) { 2112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Decorator d; 2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.EndMutex(), after); 2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) { 216a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 217ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (rm->destroyed) { 218a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Mutex()); 219ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" Mutex M%llu is already destroyed.\n\n", rm->id); 220a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndMutex()); 221ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } else { 222a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Mutex()); 2232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr); 224a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndMutex()); 225ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov PrintStack(rm->stack); 226ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov } 2277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) { 230a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->id == 0) // Little sense in describing the main thread. 2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 233a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.ThreadDescription()); 234ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov Printf(" Thread T%d", rt->id); 2352bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov if (rt->name && rt->name[0] != '\0') 236b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" '%s'", rt->name); 237da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov char thrbuf[kThreadBufSize]; 238da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" (tid=%zu, %s) created by %s", 239c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar rt->os_id, rt->running ? "running" : "finished", 240da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov thread_name(thrbuf, rt->parent_tid)); 2417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (rt->stack) 242da3503782901d30bd6e48885055b51b38cf5126cDmitry Vyukov Printf(" at:"); 243b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 244a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndThreadDescription()); 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintStack(rt->stack); 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 248848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovstatic void PrintSleep(const ReportStack *s) { 249a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 250a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Sleep()); 251b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf(" As if synchronized via sleep:\n"); 252a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndSleep()); 253848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintStack(s); 254848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 255848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 2562f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryanystatic ReportStack *ChooseSummaryStack(const ReportDesc *rep) { 2572f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->mops.Size()) 2582f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->mops[0]->stack; 2592f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->stacks.Size()) 2602f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->stacks[0]; 2612f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->mutexes.Size()) 2622f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->mutexes[0]->stack; 2632f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany if (rep->threads.Size()) 2642f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return rep->threads[0]->stack; 2652f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany return 0; 2662f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany} 2672f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 26886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic bool FrameIsInternal(const SymbolizedStack *frame) { 26986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (frame == 0) 27086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return false; 27186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const char *file = frame->info.file; 272799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const char *module = frame->info.module; 273799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (file != 0 && 274799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (internal_strstr(file, "tsan_interceptors.cc") || 275799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strstr(file, "sanitizer_common_interceptors.inc") || 276799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strstr(file, "tsan_interface_"))) 277799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return true; 278799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_"))) 279799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return true; 280799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return false; 28186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 28286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 28386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) { 28486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines while (FrameIsInternal(frames) && frames->next) 28586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines frames = frames->next; 28686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return frames; 2872f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany} 2882f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) { 290a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Decorator d; 291b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 2922f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany const char *rep_typ_str = ReportTypeString(rep->typ); 293a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.Warning()); 2940b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str, 2950b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne (int)internal_getpid()); 296a27512c4e115df4f260501a94b8d343f9ed955afKostya Serebryany Printf("%s", d.EndWarning()); 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rep->typ == ReportTypeDeadlock) { 2992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char thrbuf[kThreadBufSize]; 3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" Cycle in lock order graph: "); 3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->mutexes.Size(); i++) 3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutexShortWithAddress(rep->mutexes[i], " => "); 3032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutexShort(rep->mutexes[0], "\n\n"); 3042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_GT(rep->mutexes.Size(), 0U); 3052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_EQ(rep->mutexes.Size() * (flags()->second_deadlock_stack ? 2 : 1), 3062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines rep->stacks.Size()); 3072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->mutexes.Size(); i++) { 3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" Mutex "); 3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutexShort(rep->mutexes[(i + 1) % rep->mutexes.Size()], 3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines " acquired here while holding mutex "); 3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutexShort(rep->mutexes[i], " in "); 3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("%s", d.ThreadDescription()); 3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("%s:\n", thread_name(thrbuf, rep->unique_tids[i])); 3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("%s", d.EndThreadDescription()); 3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (flags()->second_deadlock_stack) { 3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[2*i]); 3172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" Mutex "); 3182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutexShort(rep->mutexes[i], 3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines " previously acquired by the same thread here:\n"); 3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[2*i+1]); 3212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[i]); 3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (i == 0) 3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" Hint: use TSAN_OPTIONS=second_deadlock_stack=1 " 3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "to get more informative warning message\n\n"); 3262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 3292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->stacks.Size(); i++) { 3302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (i) 3312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf(" and:\n"); 3322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[i]); 3332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 334332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov } 3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->mops.Size(); i++) 3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintMop(rep->mops[i], i == 0); 3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 339848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (rep->sleep) 340848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov PrintSleep(rep->sleep); 341848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->locs.Size(); i++) 3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintLocation(rep->locs[i]); 3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rep->typ != ReportTypeDeadlock) { 3462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->mutexes.Size(); i++) 3472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMutex(rep->mutexes[i]); 3482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < rep->threads.Size(); i++) 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany PrintThread(rep->threads[i]); 3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3534536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov if (rep->typ == ReportTypeThreadLeak && rep->count > 1) 3544536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov Printf(" And %d more similar thread leaks.\n\n", rep->count - 1); 3554536cb1fa7734133f404acb413589d7a6d314f4aDmitry Vyukov 35686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (ReportStack *stack = ChooseSummaryStack(rep)) { 3577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) 3587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ReportErrorSummary(rep_typ_str, frame->info); 3596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 3602f588f9d3417aa107ebbbd8830f97501023d3f40Kostya Serebryany 361b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 36486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else // #ifndef SANITIZER_GO 3659d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov 3669d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukovconst int kMainThreadId = 1; 367c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 3680ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukovvoid PrintStack(const ReportStack *ent) { 36986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (ent == 0 || ent->frames == 0) { 3709d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf(" [failed to restore the stack]\n"); 3716c0fbcae2f03eb78f82969bea61ccdbd2fb58e27Dmitry Vyukov return; 3726c0fbcae2f03eb78f82969bea61ccdbd2fb58e27Dmitry Vyukov } 37386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SymbolizedStack *frame = ent->frames; 37486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines for (int i = 0; frame; frame = frame->next, i++) { 37586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const AddressInfo &info = frame->info; 37686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Printf(" %s()\n %s:%d +0x%zx\n", info.function, 37786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines StripPathPrefix(info.file, common_flags()->strip_path_prefix), 37886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.line, (void *)info.module_offset); 379c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov } 380c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 381c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 382c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovstatic void PrintMop(const ReportMop *mop, bool first) { 3839d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("\n"); 384c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("%s at %p by ", 385c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov (first ? (mop->write ? "Write" : "Read") 386c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar : (mop->write ? "Previous write" : "Previous read")), mop->addr); 3879d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov if (mop->tid == kMainThreadId) 3889d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("main goroutine:\n"); 3899d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov else 3909d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("goroutine %d:\n", mop->tid); 391c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov PrintStack(mop->stack); 392c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 393c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 394c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic void PrintLocation(const ReportLocation *loc) { 395c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar switch (loc->type) { 396c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case ReportLocationHeap: { 397c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("\n"); 398c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("Heap block of size %zu at %p allocated by ", 399c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar loc->heap_chunk_size, loc->heap_chunk_start); 400c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (loc->tid == kMainThreadId) 401c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("main goroutine:\n"); 402c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar else 403c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("goroutine %d:\n", loc->tid); 404c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar PrintStack(loc->stack); 405c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 406c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 407c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case ReportLocationGlobal: { 408c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("\n"); 409c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Printf("Global var %s of size %zu at %p declared at %s:%zu\n", 410c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar loc->global.name, loc->global.size, loc->global.start, 411c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar loc->global.file, loc->global.line); 412c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 413c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 414c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar default: 415c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 416c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 417c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 418c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 41943046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukovstatic void PrintThread(const ReportThread *rt) { 4209d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov if (rt->id == kMainThreadId) 42143046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov return; 4229d95475f8adb1e08e45484feb03570ae2be2d0f3Dmitry Vyukov Printf("\n"); 423b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Goroutine %d (%s) created at:\n", 42443046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov rt->id, rt->running ? "running" : "finished"); 42543046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov PrintStack(rt->stack); 42643046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov} 42743046e0b628df7eaaec266a4b6c9e9a998b02120Dmitry Vyukov 428c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukovvoid PrintReport(const ReportDesc *rep) { 429b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 4302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rep->typ == ReportTypeRace) { 4312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("WARNING: DATA RACE"); 4322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->mops.Size(); i++) 4332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintMop(rep->mops[i], i == 0); 434c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar for (uptr i = 0; i < rep->locs.Size(); i++) 435c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar PrintLocation(rep->locs[i]); 4362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->threads.Size(); i++) 4372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintThread(rep->threads[i]); 4382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else if (rep->typ == ReportTypeDeadlock) { 4392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("WARNING: DEADLOCK\n"); 4402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < rep->mutexes.Size(); i++) { 4412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("Goroutine %d lock mutex %d while holding mutex %d:\n", 4422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 999, rep->mutexes[i]->id, 4432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines rep->mutexes[(i+1) % rep->mutexes.Size()]->id); 4442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[2*i]); 4452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("\n"); 4462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("Mutex %d was previously locked here:\n", 4472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines rep->mutexes[(i+1) % rep->mutexes.Size()]->id); 4482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStack(rep->stacks[2*i + 1]); 4492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("\n"); 4502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 4512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 452b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("==================\n"); 453c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov} 454c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 455c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov#endif 456c510a2f264a22ff60333fc48e5fa12d41cefba3cDmitry Vyukov 4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 458