Index: lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -39,7 +39,7 @@
       RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++,
                   cur->info, common_flags()->symbolize_vs_style,
                   common_flags()->strip_path_prefix);
-      Printf("%s\n", frame_desc.data());
+      Printf("    %s\n", frame_desc.data());
       if (dedup_frames-- > 0) {
         if (dedup_token.length())
           dedup_token.append("--");
Index: lib/sanitizer_common/sanitizer_stacktrace_printer.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stacktrace_printer.cc
+++ lib/sanitizer_common/sanitizer_stacktrace_printer.cc
@@ -24,7 +24,7 @@
   return function;
 }
 
-static const char kDefaultFormat[] = "    #%n %p %F %L";
+static const char kDefaultFormat[] = "#%n %p %F %L";
 
 void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
                  const AddressInfo &info, bool vs_style,
Index: lib/tsan/rtl/tsan_flags.cc
===================================================================
--- lib/tsan/rtl/tsan_flags.cc
+++ lib/tsan/rtl/tsan_flags.cc
@@ -65,7 +65,7 @@
       cf.detect_deadlocks = true;
     }
     cf.print_suppressions = false;
-    cf.stack_trace_format = "    #%n %f %S %M";
+    cf.stack_trace_format = "#%n %f %S %M";
     cf.exitcode = 66;
     cf.intercept_tls_get_addr = true;
     OverrideCommonFlags(cf);
Index: lib/tsan/rtl/tsan_report.h
===================================================================
--- lib/tsan/rtl/tsan_report.h
+++ lib/tsan/rtl/tsan_report.h
@@ -40,6 +40,7 @@
 struct ReportStack {
   SymbolizedStack *frames;
   bool suppressable;
+  SymbolizedStack *responsible_frame;
   static ReportStack *New();
 
  private:
@@ -127,7 +128,7 @@
 
 // Format and output the report to the console/log. No additional logic.
 void PrintReport(const ReportDesc *rep);
-void PrintStack(const ReportStack *stack);
+void PrintStack(const ReportStack *ent, bool mark_frames = false);
 
 }  // namespace __tsan
 
Index: lib/tsan/rtl/tsan_report.cc
===================================================================
--- lib/tsan/rtl/tsan_report.cc
+++ lib/tsan/rtl/tsan_report.cc
@@ -19,7 +19,8 @@
 
 namespace __tsan {
 
-ReportStack::ReportStack() : frames(nullptr), suppressable(false) {}
+ReportStack::ReportStack()
+    : frames(nullptr), suppressable(false), responsible_frame(0) {}
 
 ReportStack *ReportStack::New() {
   void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack));
@@ -121,7 +122,7 @@
 static const char *const kInterposedFunctionPrefix = "__interceptor_";
 #endif
 
-void PrintStack(const ReportStack *ent) {
+void PrintStack(const ReportStack *ent, bool mark_frames) {
   if (ent == 0 || ent->frames == 0) {
     Printf("    [failed to restore the stack]\n\n");
     return;
@@ -132,7 +133,9 @@
     RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info,
                 common_flags()->symbolize_vs_style,
                 common_flags()->strip_path_prefix, kInterposedFunctionPrefix);
-    Printf("%s\n", res.data());
+    const char *star_or_space =
+        (mark_frames && frame == ent->responsible_frame) ? "*" : " ";
+    Printf("  %s %s\n", star_or_space, res.data());
   }
   Printf("\n");
 }
@@ -159,7 +162,7 @@
                : (write ? "Previous mutating" : "Previous read-only");
 }
 
-static void PrintMop(const ReportMop *mop, bool first) {
+static void PrintMop(const ReportMop *mop, bool mark_frames, bool first) {
   Decorator d;
   char thrbuf[kThreadBufSize];
   Printf("%s", d.Access());
@@ -176,7 +179,7 @@
   PrintMutexSet(mop->mset);
   Printf(":\n");
   Printf("%s", d.EndAccess());
-  PrintStack(mop->stack);
+  PrintStack(mop->stack, mark_frames);
 }
 
 static void PrintLocation(const ReportLocation *loc) {
@@ -306,10 +309,17 @@
   return false;
 }
 
-static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) {
-  while (FrameIsInternal(frames) && frames->next)
-    frames = frames->next;
-  return frames;
+static bool FillResponsibleFrame(ReportStack *stack, ReportType typ) {
+  if (stack) {
+    SymbolizedStack *frame = stack->frames;
+    while (FrameIsInternal(frame) && frame->next) frame = frame->next;
+    if (typ == ReportTypeExternalRace && frame->next) frame = frame->next;
+    if (stack) {
+      stack->responsible_frame = frame;
+      return stack->responsible_frame != stack->frames;
+    }
+  }
+  return false;
 }
 
 void PrintReport(const ReportDesc *rep) {
@@ -321,6 +331,16 @@
          (int)internal_getpid());
   Printf("%s", d.EndWarning());
 
+  bool should_mark_frame = false;
+  for (uptr i = 0; i < rep->mops.Size(); i++)
+    should_mark_frame |= FillResponsibleFrame(rep->mops[i]->stack, rep->typ);
+  for (uptr i = 0; i < rep->stacks.Size(); i++)
+    should_mark_frame |= FillResponsibleFrame(rep->stacks[i], rep->typ);
+  for (uptr i = 0; i < rep->threads.Size(); i++)
+    should_mark_frame |= FillResponsibleFrame(rep->threads[i]->stack, rep->typ);
+  for (uptr i = 0; i < rep->locs.Size(); i++)
+    should_mark_frame |= FillResponsibleFrame(rep->locs[i]->stack, rep->typ);
+
   if (rep->typ == ReportTypeDeadlock) {
     char thrbuf[kThreadBufSize];
     Printf("  Cycle in lock order graph: ");
@@ -355,12 +375,16 @@
     for (uptr i = 0; i < rep->stacks.Size(); i++) {
       if (i)
         Printf("  and:\n");
-      PrintStack(rep->stacks[i]);
+      PrintStack(rep->stacks[i], should_mark_frame);
     }
   }
 
   for (uptr i = 0; i < rep->mops.Size(); i++)
-    PrintMop(rep->mops[i], i == 0);
+    PrintMop(rep->mops[i], should_mark_frame, i == 0);
+
+  if (should_mark_frame) {
+    Printf("  Issue is caused by frames marked with \"*\".\n\n");
+  }
 
   if (rep->sleep)
     PrintSleep(rep->sleep);
@@ -380,7 +404,8 @@
     Printf("  And %d more similar thread leaks.\n\n", rep->count - 1);
 
   if (ReportStack *stack = ChooseSummaryStack(rep)) {
-    if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
+    SymbolizedStack *frame = stack->responsible_frame ?: stack->frames;
+    if (frame)
       ReportErrorSummary(rep_typ_str, frame->info);
   }
 
@@ -393,7 +418,7 @@
 
 const int kMainThreadId = 1;
 
-void PrintStack(const ReportStack *ent) {
+void PrintStack(const ReportStack *ent, bool mark_frames) {
   if (ent == 0 || ent->frames == 0) {
     Printf("  [failed to restore the stack]\n");
     return;
Index: test/tsan/Darwin/external.cc
===================================================================
--- test/tsan/Darwin/external.cc
+++ test/tsan/Darwin/external.cc
@@ -94,13 +94,25 @@
 
 #else  // defined(SHARED_LIB)
 
+void UserCodeRead(MyObjectRef ref) {
+  ObjectRead(ref);
+}
+
+void UserCodeWrite(MyObjectRef ref, long val) {
+  ObjectWrite(ref, val);
+}
+
+void UserCodeWriteAnother(MyObjectRef ref, long val) {
+  ObjectWriteAnother(ref, val);
+}
+
 int main(int argc, char *argv[]) {
   InitializeLibrary();
   
   {
     MyObjectRef ref = ObjectCreate();
-    std::thread t1([ref]{ ObjectRead(ref); });
-    std::thread t2([ref]{ ObjectRead(ref); });
+    std::thread t1([ref]{ UserCodeRead(ref); });
+    std::thread t2([ref]{ UserCodeRead(ref); });
     t1.join();
     t2.join();
   }
@@ -109,11 +121,11 @@
   
   fprintf(stderr, "RR test done\n");
   // CHECK: RR test done
-
+  
   {
     MyObjectRef ref = ObjectCreate();
-    std::thread t1([ref]{ ObjectRead(ref); });
-    std::thread t2([ref]{ ObjectWrite(ref, 66); });
+    std::thread t1([ref]{ UserCodeRead(ref); });
+    std::thread t2([ref]{ UserCodeWrite(ref, 66); });
     t1.join();
     t2.join();
   }
@@ -127,19 +139,20 @@
   
   // TEST3: WARNING: ThreadSanitizer: race on a library object
   // TEST3: {{Mutating|read-only}} access of object MyLibrary::MyObject at
-  // TEST3: {{ObjectWrite|ObjectRead}}
+  // TEST3: * #1 {{UserCodeWrite|UserCodeRead}}
   // TEST3: Previous {{mutating|read-only}} access of object MyLibrary::MyObject at
-  // TEST3: {{ObjectWrite|ObjectRead}}
+  // TEST3: * #1 {{UserCodeWrite|UserCodeRead}}
+  // TEST3: Issue is caused by frames marked with "*".
   // TEST3: Location is MyLibrary::MyObject object of size 16 at
   // TEST3: {{ObjectCreate}}
-
+  
   fprintf(stderr, "RW test done\n");
   // CHECK: RW test done
-
+  
   {
     MyObjectRef ref = ObjectCreate();
-    std::thread t1([ref]{ ObjectWrite(ref, 76); });
-    std::thread t2([ref]{ ObjectWriteAnother(ref, 77); });
+    std::thread t1([ref]{ UserCodeWrite(ref, 76); });
+    std::thread t2([ref]{ UserCodeWriteAnother(ref, 77); });
     t1.join();
     t2.join();
   }
@@ -150,12 +163,13 @@
   
   // TEST3: WARNING: ThreadSanitizer: race on a library object
   // TEST3: Mutating access of object MyLibrary::MyObject at
-  // TEST3: {{ObjectWrite|ObjectWriteAnother}}
+  // TEST3: * #1 {{UserCodeWrite|UserCodeWriteAnother}}
   // TEST3: Previous mutating access of object MyLibrary::MyObject at
-  // TEST3: {{ObjectWrite|ObjectWriteAnother}}
+  // TEST3: * #1 {{UserCodeWrite|UserCodeWriteAnother}}
+  // TEST3: Issue is caused by frames marked with "*".
   // TEST3: Location is MyLibrary::MyObject object of size 16 at
   // TEST3: {{ObjectCreate}}
-
+  
   fprintf(stderr, "WW test done\n");
   // CHECK: WW test done
 }
Index: test/tsan/free_race.c
===================================================================
--- test/tsan/free_race.c
+++ test/tsan/free_race.c
@@ -37,11 +37,12 @@
 
 // CHECK-NOZUPP: WARNING: ThreadSanitizer: heap-use-after-free
 // CHECK-NOZUPP:   Write of size 4 at {{.*}} by main thread{{.*}}:
-// CHECK-NOZUPP:     #0 Thread2
+// CHECK-NOZUPP:   * #0 Thread2
 // CHECK-NOZUPP:     #1 main
 // CHECK-NOZUPP:   Previous write of size 8 at {{.*}} by thread T1{{.*}}:
 // CHECK-NOZUPP:     #0 free
-// CHECK-NOZUPP:     #{{(1|2)}} Thread1
+// CHECK-NOZUPP:   * #{{(1|2)}} Thread1
+// CHECK-NOZUPP:   Issue is caused by frames marked with "*".
 // CHECK-NOZUPP: SUMMARY: ThreadSanitizer: heap-use-after-free{{.*}}Thread2
 // CHECK-SUPP:   ThreadSanitizer: Matched 1 suppressions
 // CHECK-SUPP:    1 race:^Thread2$
Index: test/tsan/memcmp_race.cc
===================================================================
--- test/tsan/memcmp_race.cc
+++ test/tsan/memcmp_race.cc
@@ -36,7 +36,8 @@
 // CHECK: WARNING: ThreadSanitizer: data race
 // CHECK:   Write of size 1 at [[ADDR]] by thread T2:
 // CHECK:     #0 {{(memcpy|memmove)}}
-// CHECK:     #1 Thread2
+// CHECK:   * #1 Thread2
 // CHECK:   Previous read of size 1 at [[ADDR]] by thread T1:
 // CHECK:     #0 memcmp
-// CHECK:     #1 Thread1
+// CHECK:   * #1 Thread1
+// CHECK:   Issue is caused by frames marked with "*".
Index: test/tsan/memcpy_race.cc
===================================================================
--- test/tsan/memcpy_race.cc
+++ test/tsan/memcpy_race.cc
@@ -35,7 +35,8 @@
 // CHECK: WARNING: ThreadSanitizer: data race
 // CHECK:   Write of size 1 at [[ADDR]] by thread T2:
 // CHECK:     #0 {{(memcpy|memmove)}}
-// CHECK:     #1 Thread2
+// CHECK:   * #1 Thread2
 // CHECK:   Previous write of size 1 at [[ADDR]] by thread T1:
 // CHECK:     #0 {{(memcpy|memmove)}}
-// CHECK:     #1 Thread1
+// CHECK:   * #1 Thread1
+// CHECK:   Issue is caused by frames marked with "*".
Index: test/tsan/mutex_destroy_locked.cc
===================================================================
--- test/tsan/mutex_destroy_locked.cc
+++ test/tsan/mutex_destroy_locked.cc
@@ -12,10 +12,11 @@
 
 // CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
 // CHECK:     #0 pthread_mutex_destroy
-// CHECK:     #1 main
+// CHECK:   * #1 main
 // CHECK:   and:
 // CHECK:     #0 pthread_mutex_lock
-// CHECK:     #1 main
+// CHECK:   * #1 main
+// CHECK:   Issue is caused by frames marked with "*".
 // CHECK:   Mutex {{.*}} created at:
 // CHECK:     #0 pthread_mutex_init
 // CHECK:     #1 main