[llvm-commits] [compiler-rt] r169601 - in /compiler-rt/trunk/lib/asan: asan_interceptors.cc asan_report.cc asan_thread.h tests/asan_test.cc

Kostya Serebryany kcc at google.com
Fri Dec 7 07:15:02 PST 2012


Author: kcc
Date: Fri Dec  7 09:15:01 2012
New Revision: 169601

URL: http://llvm.org/viewvc/llvm-project?rev=169601&view=rev
Log:
[asan] intercept prctl(PR_SET_NAME) and set the thread name. Output the thread names (if non-empty) in asan reports

Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_thread.h
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=169601&r1=169600&r2=169601&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri Dec  7 09:15:01 2012
@@ -177,6 +177,23 @@
 }
 #endif
 
+#define PR_SET_NAME 15
+
+INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
+            unsigned long arg4, unsigned long arg5) {
+  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
+  if (option == PR_SET_NAME) {
+    AsanThread *t = asanThreadRegistry().GetCurrent();
+    if (t) {
+      char buff[17];
+      internal_strncpy(buff, (char*)arg2, 16);
+      buff[16] = 0;
+      t->summary()->set_name(buff);
+    }
+  }
+  return res;
+}
+
 #if ASAN_INTERCEPT___CXA_THROW
 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
   CHECK(REAL(__cxa_throw));
@@ -720,6 +737,7 @@
 #if ASAN_INTERCEPT_SIGLONGJMP
   ASAN_INTERCEPT_FUNC(siglongjmp);
 #endif
+  ASAN_INTERCEPT_FUNC(prctl);
 
   // Intercept exception handling functions.
 #if ASAN_INTERCEPT___CXA_THROW

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=169601&r1=169600&r2=169601&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Fri Dec  7 09:15:01 2012
@@ -203,6 +203,25 @@
          (void*)(chunk.Beg()), (void*)(chunk.End()));
 }
 
+// Return " (thread_name) " or an empty string if the name is empty.
+const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
+                                      uptr buff_len) {
+  const char *name = t->name();
+  if (*name == 0) return "";
+  buff[0] = 0;
+  internal_strncat(buff, " (", 3);
+  internal_strncat(buff, name, buff_len - 4);
+  internal_strncat(buff, ")", 2);
+  return buff;
+}
+
+const char *ThreadNameWithParenthesis(u32 tid, char buff[],
+                                      uptr buff_len) {
+  if (tid == kInvalidTid) return "";
+  AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid);
+  return ThreadNameWithParenthesis(t, buff, buff_len);
+}
+
 void DescribeHeapAddress(uptr addr, uptr access_size) {
   AsanChunkView chunk = FindHeapChunkByAddress(addr);
   if (!chunk.IsValid()) return;
@@ -214,20 +233,25 @@
   chunk.GetAllocStack(&alloc_stack);
   AsanThread *t = asanThreadRegistry().GetCurrent();
   CHECK(t);
+  char tname[128];
   if (chunk.FreeTid() != kInvalidTid) {
     AsanThreadSummary *free_thread =
         asanThreadRegistry().FindByTid(chunk.FreeTid());
-    Printf("freed by thread T%d here:\n", free_thread->tid());
+    Printf("freed by thread T%d%s here:\n", free_thread->tid(),
+           ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)));
     StackTrace free_stack;
     chunk.GetFreeStack(&free_stack);
     PrintStack(&free_stack);
-    Printf("previously allocated by thread T%d here:\n", alloc_thread->tid());
+    Printf("previously allocated by thread T%d%s here:\n",
+           alloc_thread->tid(),
+           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)));
     PrintStack(&alloc_stack);
     DescribeThread(t->summary());
     DescribeThread(free_thread);
     DescribeThread(alloc_thread);
   } else {
-    Printf("allocated by thread T%d here:\n", alloc_thread->tid());
+    Printf("allocated by thread T%d%s here:\n", alloc_thread->tid(),
+           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)));
     PrintStack(&alloc_stack);
     DescribeThread(t->summary());
     DescribeThread(alloc_thread);
@@ -256,8 +280,13 @@
     return;
   }
   summary->set_announced(true);
-  Printf("Thread T%d created by T%d here:\n",
-         summary->tid(), summary->parent_tid());
+  char tname[128];
+  Printf("Thread T%d%s", summary->tid(),
+         ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
+  Printf(" created by T%d%s here:\n",
+         summary->parent_tid(),
+         ThreadNameWithParenthesis(summary->parent_tid(),
+                                   tname, sizeof(tname)));
   PrintStack(summary->stack());
   // Recursively described parent thread if needed.
   if (flags()->print_full_thread_history) {
@@ -471,9 +500,11 @@
              bug_descr, (void*)addr, pc, bp, sp);
 
   u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
-  Printf("%s of size %zu at %p thread T%d\n",
+  char tname[128];
+  Printf("%s of size %zu at %p thread T%d%s\n",
              access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
-             access_size, (void*)addr, curr_tid);
+             access_size, (void*)addr, curr_tid,
+             ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
 
   GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
   PrintStack(&stack);

Modified: compiler-rt/trunk/lib/asan/asan_thread.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.h?rev=169601&r1=169600&r2=169601&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.h (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.h Fri Dec  7 09:15:01 2012
@@ -39,6 +39,7 @@
       internal_memcpy(&stack_, stack, sizeof(*stack));
     }
     thread_ = 0;
+    name_[0] = 0;
   }
   u32 tid() { return tid_; }
   void set_tid(u32 tid) { tid_ = tid; }
@@ -49,6 +50,10 @@
   AsanThread *thread() { return thread_; }
   void set_thread(AsanThread *thread) { thread_ = thread; }
   static void TSDDtor(void *tsd);
+  void set_name(const char *name) {
+    internal_strncpy(name_, name, sizeof(name_) - 1);
+  }
+  const char *name() { return name_; }
 
  private:
   u32 tid_;
@@ -56,8 +61,12 @@
   bool announced_;
   StackTrace stack_;
   AsanThread *thread_;
+  char name_[128];
 };
 
+// AsanThreadSummary objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(AsanThreadSummary) <= 4094);
+
 // AsanThread are stored in TSD and destroyed when the thread dies.
 class AsanThread {
  public:

Modified: compiler-rt/trunk/lib/asan/tests/asan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_test.cc?rev=169601&r1=169600&r2=169601&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Fri Dec  7 09:15:01 2012
@@ -20,6 +20,10 @@
 #include <setjmp.h>
 #include <assert.h>
 
+#ifdef __linux__
+# include <sys/prctl.h>
+#endif
+
 #if defined(__i386__) || defined(__x86_64__)
 #include <emmintrin.h>
 #endif
@@ -1619,19 +1623,28 @@
                "malloc_fff.*malloc_eee.*malloc_ddd");
 }
 
+static void TryToSetThreadName(const char *name) {
+#ifdef __linux__
+  prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
+#endif
+}
+
 void *ThreadedTestAlloc(void *a) {
+  TryToSetThreadName("AllocThr");
   int **p = (int**)a;
   *p = new int;
   return 0;
 }
 
 void *ThreadedTestFree(void *a) {
+  TryToSetThreadName("FreeThr");
   int **p = (int**)a;
   delete *p;
   return 0;
 }
 
 void *ThreadedTestUse(void *a) {
+  TryToSetThreadName("UseThr");
   int **p = (int**)a;
   **p = 1;
   return 0;
@@ -1656,6 +1669,22 @@
                ".*Thread T.*created");
 }
 
+#ifdef __linux__
+TEST(AddressSanitizer, ThreadNamesTest) {
+  // ThreadedTestSpawn();
+  EXPECT_DEATH(ThreadedTestSpawn(),
+               ASAN_PCRE_DOTALL
+               "WRITE .*thread T3 .UseThr."
+               ".*freed by thread T2 .FreeThr. here:"
+               ".*previously allocated by thread T1 .AllocThr. here:"
+               ".*Thread T3 .UseThr. created by T0 here:"
+               ".*Thread T2 .FreeThr. created by T0 here:"
+               ".*Thread T1 .AllocThr. created by T0 here:"
+               "");
+
+}
+#endif
+
 #if ASAN_NEEDS_SEGV
 TEST(AddressSanitizer, ShadowGapTest) {
 #if SANITIZER_WORDSIZE == 32





More information about the llvm-commits mailing list