diff options
author | Wei Mi <wmi@google.com> | 2012-11-22 22:03:11 +0000 |
---|---|---|
committer | Wei Mi <wmi@gcc.gnu.org> | 2012-11-22 22:03:11 +0000 |
commit | cd0be65c262d477ac094fc1038824f766d976999 (patch) | |
tree | f83ad11b95452b47f813e942d24914f31a50394e /libsanitizer/tsan/tsan_report.cc | |
parent | 32b4b7f53e341be663438f69fd6cb2f909427188 (diff) | |
download | gcc-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.cc | 183 |
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 |