aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/tsan/tsan_report.cc
diff options
context:
space:
mode:
authorWei Mi <wmi@google.com>2012-11-22 22:03:11 +0000
committerWei Mi <wmi@gcc.gnu.org>2012-11-22 22:03:11 +0000
commitcd0be65c262d477ac094fc1038824f766d976999 (patch)
treef83ad11b95452b47f813e942d24914f31a50394e /libsanitizer/tsan/tsan_report.cc
parent32b4b7f53e341be663438f69fd6cb2f909427188 (diff)
downloadgcc-cd0be65c262d477ac094fc1038824f766d976999.zip
gcc-cd0be65c262d477ac094fc1038824f766d976999.tar.gz
gcc-cd0be65c262d477ac094fc1038824f766d976999.tar.bz2
tsan: New directory.
libsanitizer/ * tsan: New directory. Import tsan runtime from llvm. * configure.ac: Add 64 bits tsan build. * Makefile.am: Likewise. * configure: Regenerated. * Makefile.in: Likewise. From-SVN: r193737
Diffstat (limited to 'libsanitizer/tsan/tsan_report.cc')
-rw-r--r--libsanitizer/tsan/tsan_report.cc183
1 files changed, 183 insertions, 0 deletions
diff --git a/libsanitizer/tsan/tsan_report.cc b/libsanitizer/tsan/tsan_report.cc
new file mode 100644
index 0000000..716a20f
--- /dev/null
+++ b/libsanitizer/tsan/tsan_report.cc
@@ -0,0 +1,183 @@
+//===-- tsan_report.cc ----------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_report.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+ReportDesc::ReportDesc()
+ : stacks(MBlockReportStack)
+ , mops(MBlockReportMop)
+ , locs(MBlockReportLoc)
+ , mutexes(MBlockReportMutex)
+ , threads(MBlockReportThread)
+ , sleep() {
+}
+
+ReportDesc::~ReportDesc() {
+}
+
+#ifndef TSAN_GO
+
+static void PrintHeader(ReportType typ) {
+ TsanPrintf("WARNING: ThreadSanitizer: ");
+
+ if (typ == ReportTypeRace)
+ TsanPrintf("data race");
+ else if (typ == ReportTypeUseAfterFree)
+ TsanPrintf("heap-use-after-free");
+ else if (typ == ReportTypeThreadLeak)
+ TsanPrintf("thread leak");
+ else if (typ == ReportTypeMutexDestroyLocked)
+ TsanPrintf("destroy of a locked mutex");
+ else if (typ == ReportTypeSignalUnsafe)
+ TsanPrintf("signal-unsafe call inside of a signal");
+ else if (typ == ReportTypeErrnoInSignal)
+ TsanPrintf("signal handler spoils errno");
+
+ TsanPrintf(" (pid=%d)\n", GetPid());
+}
+
+void PrintStack(const ReportStack *ent) {
+ for (int i = 0; ent; ent = ent->next, i++) {
+ TsanPrintf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line);
+ if (ent->col)
+ TsanPrintf(":%d", ent->col);
+ if (ent->module && ent->offset)
+ TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset);
+ else
+ TsanPrintf(" (%p)\n", (void*)ent->pc);
+ }
+ TsanPrintf("\n");
+}
+
+static void PrintMop(const ReportMop *mop, bool first) {
+ TsanPrintf(" %s of size %d at %p",
+ (first ? (mop->write ? "Write" : "Read")
+ : (mop->write ? "Previous write" : "Previous read")),
+ mop->size, (void*)mop->addr);
+ if (mop->tid == 0)
+ TsanPrintf(" by main thread:\n");
+ else
+ TsanPrintf(" by thread %d:\n", mop->tid);
+ PrintStack(mop->stack);
+}
+
+static void PrintLocation(const ReportLocation *loc) {
+ if (loc->type == ReportLocationGlobal) {
+ TsanPrintf(" Location is global '%s' of size %zu at %zx %s:%d\n",
+ loc->name, loc->size, loc->addr, loc->file, loc->line);
+ } else if (loc->type == ReportLocationHeap) {
+ TsanPrintf(" Location is heap block of size %zu at %p allocated",
+ loc->size, loc->addr);
+ if (loc->tid == 0)
+ TsanPrintf(" by main thread:\n");
+ else
+ TsanPrintf(" by thread %d:\n", loc->tid);
+ PrintStack(loc->stack);
+ } else if (loc->type == ReportLocationStack) {
+ TsanPrintf(" Location is stack of thread %d:\n", loc->tid);
+ }
+}
+
+static void PrintMutex(const ReportMutex *rm) {
+ if (rm->stack == 0)
+ return;
+ TsanPrintf(" Mutex %d created at:\n", rm->id);
+ PrintStack(rm->stack);
+}
+
+static void PrintThread(const ReportThread *rt) {
+ if (rt->id == 0) // Little sense in describing the main thread.
+ return;
+ TsanPrintf(" Thread %d", rt->id);
+ if (rt->name)
+ TsanPrintf(" '%s'", rt->name);
+ TsanPrintf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
+ if (rt->stack)
+ TsanPrintf(" created at:");
+ TsanPrintf("\n");
+ PrintStack(rt->stack);
+}
+
+static void PrintSleep(const ReportStack *s) {
+ TsanPrintf(" As if synchronized via sleep:\n");
+ PrintStack(s);
+}
+
+void PrintReport(const ReportDesc *rep) {
+ TsanPrintf("==================\n");
+ PrintHeader(rep->typ);
+
+ for (uptr i = 0; i < rep->stacks.Size(); i++) {
+ if (i)
+ TsanPrintf(" and:\n");
+ PrintStack(rep->stacks[i]);
+ }
+
+ for (uptr i = 0; i < rep->mops.Size(); i++)
+ PrintMop(rep->mops[i], i == 0);
+
+ if (rep->sleep)
+ PrintSleep(rep->sleep);
+
+ for (uptr i = 0; i < rep->locs.Size(); i++)
+ PrintLocation(rep->locs[i]);
+
+ for (uptr i = 0; i < rep->mutexes.Size(); i++)
+ PrintMutex(rep->mutexes[i]);
+
+ for (uptr i = 0; i < rep->threads.Size(); i++)
+ PrintThread(rep->threads[i]);
+
+ TsanPrintf("==================\n");
+}
+
+#else
+
+void PrintStack(const ReportStack *ent) {
+ for (int i = 0; ent; ent = ent->next, i++) {
+ TsanPrintf(" %s()\n %s:%d +0x%zx\n",
+ ent->func, ent->file, ent->line, (void*)ent->offset);
+ }
+ TsanPrintf("\n");
+}
+
+static void PrintMop(const ReportMop *mop, bool first) {
+ TsanPrintf("%s by goroutine %d:\n",
+ (first ? (mop->write ? "Write" : "Read")
+ : (mop->write ? "Previous write" : "Previous read")),
+ mop->tid);
+ PrintStack(mop->stack);
+}
+
+static void PrintThread(const ReportThread *rt) {
+ if (rt->id == 0) // Little sense in describing the main thread.
+ return;
+ TsanPrintf("Goroutine %d (%s) created at:\n",
+ rt->id, rt->running ? "running" : "finished");
+ PrintStack(rt->stack);
+}
+
+void PrintReport(const ReportDesc *rep) {
+ TsanPrintf("==================\n");
+ TsanPrintf("WARNING: DATA RACE\n");
+ for (uptr i = 0; i < rep->mops.Size(); i++)
+ PrintMop(rep->mops[i], i == 0);
+ for (uptr i = 0; i < rep->threads.Size(); i++)
+ PrintThread(rep->threads[i]);
+ TsanPrintf("==================\n");
+}
+
+#endif
+
+} // namespace __tsan