tsan_report.cc revision 67a64dd8259fdbd867633b27f54d584f435f1ce6
1//===-- tsan_report.cc ----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer (TSan), a race detector.
11//
12//===----------------------------------------------------------------------===//
13#include "tsan_report.h"
14#include "tsan_platform.h"
15#include "tsan_rtl.h"
16
17namespace __tsan {
18
19ReportDesc::ReportDesc()
20    : stacks(MBlockReportStack)
21    , mops(MBlockReportMop)
22    , locs(MBlockReportLoc)
23    , mutexes(MBlockReportMutex)
24    , threads(MBlockReportThread) {
25}
26
27ReportDesc::~ReportDesc() {
28}
29
30static void PrintHeader(ReportType typ) {
31  TsanPrintf("WARNING: ThreadSanitizer: ");
32
33  if (typ == ReportTypeRace)
34    TsanPrintf("data race");
35  else if (typ == ReportTypeUseAfterFree)
36    TsanPrintf("heap-use-after-free");
37  else if (typ == ReportTypeThreadLeak)
38    TsanPrintf("thread leak");
39  else if (typ == ReportTypeMutexDestroyLocked)
40    TsanPrintf("destroy of a locked mutex");
41  else if (typ == ReportTypeSignalUnsafe)
42    TsanPrintf("signal-unsafe call inside of a signal");
43
44  TsanPrintf(" (pid=%d)\n", GetPid());
45}
46
47static void PrintStack(const ReportStack *ent) {
48  for (int i = 0; ent; ent = ent->next, i++) {
49    TsanPrintf("    #%d %s %s:%d", i, ent->func, ent->file, ent->line);
50    if (ent->col)
51      TsanPrintf(":%d", ent->col);
52    if (ent->module && ent->offset)
53      TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset);
54    else
55      TsanPrintf(" (%p)\n", (void*)ent->pc);
56  }
57}
58
59static void PrintMop(const ReportMop *mop, bool first) {
60  TsanPrintf("  %s of size %d at %p",
61      (first ? (mop->write ? "Write" : "Read")
62             : (mop->write ? "Previous write" : "Previous read")),
63      mop->size, (void*)mop->addr);
64  if (mop->tid == 0)
65    TsanPrintf(" by main thread:\n");
66  else
67    TsanPrintf(" by thread %d:\n", mop->tid);
68  PrintStack(mop->stack);
69}
70
71static void PrintLocation(const ReportLocation *loc) {
72  if (loc->type == ReportLocationGlobal) {
73    TsanPrintf("  Location is global '%s' of size %lu at %lx %s:%d\n",
74               loc->name, loc->size, loc->addr, loc->file, loc->line);
75  } else if (loc->type == ReportLocationHeap) {
76    TsanPrintf("  Location is heap of size %lu at %lx allocated "
77               "by thread %d:\n", loc->size, loc->addr, loc->tid);
78    PrintStack(loc->stack);
79  } else if (loc->type == ReportLocationStack) {
80    TsanPrintf("  Location is stack of thread %d:\n", loc->tid);
81  }
82}
83
84static void PrintMutex(const ReportMutex *rm) {
85  if (rm->stack == 0)
86    return;
87  TsanPrintf("  Mutex %d created at:\n", rm->id);
88  PrintStack(rm->stack);
89}
90
91static void PrintThread(const ReportThread *rt) {
92  if (rt->id == 0)  // Little sense in describing the main thread.
93    return;
94  TsanPrintf("  Thread %d", rt->id);
95  if (rt->name)
96    TsanPrintf(" '%s'", rt->name);
97  TsanPrintf(" (%s)", rt->running ? "running" : "finished");
98  if (rt->stack)
99    TsanPrintf(" created at:");
100  TsanPrintf("\n");
101  PrintStack(rt->stack);
102}
103
104void PrintReport(const ReportDesc *rep) {
105  TsanPrintf("==================\n");
106  PrintHeader(rep->typ);
107
108  for (uptr i = 0; i < rep->stacks.Size(); i++)
109    PrintStack(rep->stacks[i]);
110
111  for (uptr i = 0; i < rep->mops.Size(); i++)
112    PrintMop(rep->mops[i], i == 0);
113
114  for (uptr i = 0; i < rep->locs.Size(); i++)
115    PrintLocation(rep->locs[i]);
116
117  for (uptr i = 0; i < rep->mutexes.Size(); i++)
118    PrintMutex(rep->mutexes[i]);
119
120  for (uptr i = 0; i < rep->threads.Size(); i++)
121    PrintThread(rep->threads[i]);
122
123  TsanPrintf("==================\n");
124}
125
126}  // namespace __tsan
127