tsan: Go lang: symbolize stack traces


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@159827 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh
index 9483909..c4cff83 100755
--- a/lib/tsan/go/buildgo.sh
+++ b/lib/tsan/go/buildgo.sh
@@ -16,7 +16,6 @@
 	../rtl/tsan_rtl_thread.cc
 	../rtl/tsan_stat.cc
 	../rtl/tsan_suppressions.cc
-	../rtl/tsan_symbolize.cc
 	../rtl/tsan_sync.cc
 	../../sanitizer_common/sanitizer_allocator.cc
 	../../sanitizer_common/sanitizer_common.cc
@@ -47,3 +46,6 @@
 echo as gotsan.s -o gotsan.syso
 as gotsan.s -o gotsan.syso
 
+gcc test.c gotsan.syso -lpthread -o test
+./test
+
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc
index bd264c9..9f4df9e 100644
--- a/lib/tsan/go/tsan_go.cc
+++ b/lib/tsan/go/tsan_go.cc
@@ -37,14 +37,40 @@
 void internal_start_thread(void(*func)(void*), void *arg) {
 }
 
-ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
-  return NewReportStackEntry(addr);
+extern "C" int goCallbackCommentPc(uptr pc, char **img, char **rtn,
+                                   char **filename, int *lineno);
+extern "C" void __libc_free(void *p);
+
+ReportStack *SymbolizeCode(uptr addr) {
+  ReportStack *s = NewReportStackEntry(addr);
+  char *img, *rtn, *filename;
+  int lineno;
+  if (goCallbackCommentPc(addr, &img, &rtn, &filename, &lineno)) {
+    s->module = internal_strdup(img);
+    s->offset = addr;
+    s->func = internal_strdup(rtn);
+    s->file = internal_strdup(filename);
+    s->line = lineno;
+    s->col = 0;
+    __libc_free(img);
+    __libc_free(rtn);
+    __libc_free(filename);
+  }
+  return s;
 }
 
-ReportStack *SymbolizeDataAddr2Line(uptr addr) {
+ReportStack *SymbolizeData(uptr addr) {
   return 0;
 }
 
+ReportStack *NewReportStackEntry(uptr addr) {
+  ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
+                                                  sizeof(ReportStack));
+  internal_memset(ent, 0, sizeof(*ent));
+  ent->pc = addr;
+  return ent;
+}
+
 void *internal_alloc(MBlockType typ, uptr sz) {
   return InternalAlloc(sz);
 }
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index cc3b5d7..a4aca66 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -27,6 +27,8 @@
 ReportDesc::~ReportDesc() {
 }
 
+#ifndef TSAN_GO
+
 static void PrintHeader(ReportType typ) {
   TsanPrintf("WARNING: ThreadSanitizer: ");
 
@@ -125,4 +127,31 @@
   TsanPrintf("==================\n");
 }
 
+#else
+
+static void PrintStack(const ReportStack *ent) {
+  for (int i = 0; ent; ent = ent->next, i++) {
+    TsanPrintf("  %s()\n      %s:%d +%p\n",
+        ent->func, ent->file, ent->line, (void*)ent->pc);
+  }
+}
+
+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);
+}
+
+void PrintReport(const ReportDesc *rep) {
+  TsanPrintf("==================\n");
+  TsanPrintf("WARNING: DATA RACE at %p\n", (void*)rep->mops[0]->addr);
+  for (uptr i = 0; i < rep->mops.Size(); i++)
+    PrintMop(rep->mops[i], i == 0);
+  TsanPrintf("==================\n");
+}
+
+#endif
+
 }  // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index c6832da..bc84275 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -43,6 +43,7 @@
 }
 
 static void StackStripMain(ReportStack *stack) {
+#ifndef TSAN_GO
   ReportStack *last_frame = 0;
   ReportStack *last_frame2 = 0;
   const char *prefix = "__interceptor_";
@@ -82,6 +83,7 @@
     // due to our fault.
     TsanPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc);
   }
+#endif
 }
 
 static ReportStack *SymbolizeStack(const StackTrace& trace) {