tsan_report.cc revision 069ce828e3057819ee34426496ea7080f7cc52f0
17ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===-- tsan_report.cc ------------------------------------------*- C++ -*-===//
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
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintHeader(ReportType typ) {
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("WARNING: ThreadSanitizer: ");
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (typ == ReportTypeRace)
347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("data race");
35069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  else if (typ == ReportTypeUseAfterFree)
36069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov    Printf("heap-use-after-free");
377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeThreadLeak)
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("thread leak");
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeMutexDestroyLocked)
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("destroy of a locked mutex");
417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (typ == ReportTypeSignalUnsafe)
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("signal-unsafe call inside of a signal");
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf(" (pid=%d)\n", GetPid());
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintStack(const ReportStack *ent) {
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (int i = 0; ent; ent = ent->next, i++) {
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("    #%d %s %s:%d", i, ent->func, ent->file, ent->line);
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (ent->col)
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Printf(":%d", ent->col);
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (ent->module && ent->offset)
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Printf(" (%s+%p)\n", ent->module, (void*)ent->offset);
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    else
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Printf(" (%p)\n", (void*)ent->pc);
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMop(const ReportMop *mop, bool first) {
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("  %s of size %d at %p",
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (first ? (mop->write ? "Write" : "Read")
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany             : (mop->write ? "Previous write" : "Previous read")),
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      mop->size, (void*)mop->addr);
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (mop->tid == 0)
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf(" by main thread:\n");
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf(" by thread %d:\n", mop->tid);
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  PrintStack(mop->stack);
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintLocation(const ReportLocation *loc) {
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (loc->type == ReportLocationGlobal) {
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("  Location is global '%s' of size %lu at %lx %s:%d\n",
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany           loc->name, loc->size, loc->addr, loc->file, loc->line);
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (loc->type == ReportLocationHeap) {
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("  Location is heap of size %lu at %lx allocated by thread %d:\n",
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany           loc->size, loc->addr, loc->tid);
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintStack(loc->stack);
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (loc->type == ReportLocationStack) {
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf("  Location is stack of thread %d:\n", loc->tid);
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintMutex(const ReportMutex *rm) {
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (rm->stack == 0)
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("  Mutex %d created at:\n", rm->id);
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  PrintStack(rm->stack);
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void PrintThread(const ReportThread *rt) {
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (rt->id == 0)  // Little sense in describing the main thread.
937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("  Thread %d", rt->id);
957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (rt->name)
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf(" '%s'", rt->name);
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf(" (%s)", rt->running ? "running" : "finished");
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (rt->stack)
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Printf(" created at:");
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("\n");
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  PrintStack(rt->stack);
1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid PrintReport(const ReportDesc *rep) {
1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("==================\n");
1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  PrintHeader(rep->typ);
1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (uptr i = 0; i < rep->stacks.Size(); i++)
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintStack(rep->stacks[i]);
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (uptr i = 0; i < rep->mops.Size(); i++)
1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintMop(rep->mops[i], i == 0);
1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (uptr i = 0; i < rep->locs.Size(); i++)
1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintLocation(rep->locs[i]);
1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (uptr i = 0; i < rep->mutexes.Size(); i++)
1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintMutex(rep->mutexes[i]);
1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (uptr i = 0; i < rep->threads.Size(); i++)
1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    PrintThread(rep->threads[i]);
1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Printf("==================\n");
1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
127