[compiler-rt] r189767 - tsan: properly intercept pthread_cond functions

Dmitry Vyukov dvyukov at google.com
Mon Sep 2 11:06:28 PDT 2013


Author: dvyukov
Date: Mon Sep  2 13:06:28 2013
New Revision: 189767

URL: http://llvm.org/viewvc/llvm-project?rev=189767&view=rev
Log:
tsan: properly intercept pthread_cond functions

Added:
    compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
Modified:
    compiler-rt/trunk/lib/interception/interception_linux.cc
    compiler-rt/trunk/lib/interception/interception_linux.h
    compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h

Modified: compiler-rt/trunk/lib/interception/interception_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.cc?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_linux.cc (original)
+++ compiler-rt/trunk/lib/interception/interception_linux.cc Mon Sep  2 13:06:28 2013
@@ -15,7 +15,6 @@
 #ifdef __linux__
 #include "interception.h"
 
-#include <stddef.h>  // for NULL
 #include <dlfcn.h>   // for dlsym
 
 namespace __interception {
@@ -24,6 +23,11 @@ bool GetRealFunctionAddress(const char *
   *func_addr = (uptr)dlsym(RTLD_NEXT, func_name);
   return real == wrapper;
 }
+
+void *GetFuncAddrVer(const char *func_name, const char *ver) {
+  return dlvsym(RTLD_NEXT, func_name, ver);
+}
+
 }  // namespace __interception
 
 

Modified: compiler-rt/trunk/lib/interception/interception_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.h?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_linux.h (original)
+++ compiler-rt/trunk/lib/interception/interception_linux.h Mon Sep  2 13:06:28 2013
@@ -25,6 +25,7 @@ namespace __interception {
 // returns true if a function with the given name was found.
 bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
     uptr real, uptr wrapper);
+void *GetFuncAddrVer(const char *func_name, const char *ver);
 }  // namespace __interception
 
 #define INTERCEPT_FUNCTION_LINUX(func) \
@@ -33,5 +34,10 @@ bool GetRealFunctionAddress(const char *
           (::__interception::uptr)&(func), \
           (::__interception::uptr)&WRAP(func))
 
+#define INTERCEPT_FUNCTION_VER(func, funcver, symver) \
+    __asm__(".symver "#funcver","#func"@"#symver); \
+    ::__interception::real_##funcver = (funcver##_f)(unsigned long) \
+        ::__interception::GetFuncAddrVer(#func, #symver)
+
 #endif  // INTERCEPTION_LINUX_H
 #endif  // __linux__

Added: compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c?rev=189767&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c Mon Sep  2 13:06:28 2013
@@ -0,0 +1,44 @@
+// RUN: %clang_tsan -O1 %s -o %t -lrt && %t 2>&1 | FileCheck %s
+// Test that pthread_cond is properly intercepted,
+// previously there were issues with versioned symbols.
+// CHECK: OK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+#include <errno.h>
+
+int main() {
+  typedef unsigned long long u64;
+  pthread_mutex_t m;
+  pthread_cond_t c;
+  pthread_condattr_t at;
+  struct timespec ts0, ts1, ts2;
+  int res;
+  u64 sleep;
+
+  pthread_mutex_init(&m, 0);
+  pthread_condattr_init(&at);
+  pthread_condattr_setclock(&at, CLOCK_MONOTONIC);
+  pthread_cond_init(&c, &at);
+
+  clock_gettime(CLOCK_MONOTONIC, &ts0);
+  ts1 = ts0;
+  ts1.tv_sec += 2;
+
+  pthread_mutex_lock(&m);
+  do {
+    res = pthread_cond_timedwait(&c, &m, &ts1);
+  } while (res == 0);
+  pthread_mutex_unlock(&m);
+
+  clock_gettime(CLOCK_MONOTONIC, &ts2);
+  sleep = (u64)ts2.tv_sec * 1000000000 + ts2.tv_nsec -
+      ((u64)ts0.tv_sec * 1000000000 + ts0.tv_nsec);
+  if (res != ETIMEDOUT)
+    exit(printf("bad return value %d, want %d\n", res, ETIMEDOUT));
+  if (sleep < 1000000000)
+    exit(printf("bad sleep duration %lluns, want %dns\n", sleep, 1000000000));
+  fprintf(stderr, "OK\n");
+}

Modified: compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh Mon Sep  2 13:06:28 2013
@@ -13,7 +13,7 @@ BLACKLIST=$ROOTDIR/lit_tests/Helpers/bla
 
 # TODO: add testing for all of -O0...-O3
 CFLAGS="-fsanitize=thread -fsanitize-blacklist=$BLACKLIST -fPIE -O1 -g -Wall"
-LDFLAGS="-pie -lpthread -ldl $ROOTDIR/rtl/libtsan.a"
+LDFLAGS="-pie -lpthread -ldl -lrt $ROOTDIR/rtl/libtsan.a"
 
 test_file() {
   SRC=$1

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon Sep  2 13:06:28 2013
@@ -1051,46 +1051,43 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unl
   return res;
 }
 
-// libpthread.so contains several versions of pthread_cond_init symbol.
-// When we just dlsym() it, we get the wrong (old) version.
-/*
-TSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
-  int res = REAL(pthread_cond_init)(c, a);
+TSAN_INTERCEPTOR(int, pthread_cond_init_2_3_2, void *c, void *a) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init_2_3_2, c, a);
+  int res = REAL(pthread_cond_init_2_3_2)(c, a);
   return res;
 }
-*/
 
-TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
-  int res = REAL(pthread_cond_destroy)(c);
+TSAN_INTERCEPTOR(int, pthread_cond_destroy_2_3_2, void *c) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy_2_3_2, c);
+  int res = REAL(pthread_cond_destroy_2_3_2)(c);
   return res;
 }
 
-TSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
-  int res = REAL(pthread_cond_signal)(c);
+TSAN_INTERCEPTOR(int, pthread_cond_signal_2_3_2, void *c) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal_2_3_2, c);
+  int res = REAL(pthread_cond_signal_2_3_2)(c);
   return res;
 }
 
-TSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
-  int res = REAL(pthread_cond_broadcast)(c);
+TSAN_INTERCEPTOR(int, pthread_cond_broadcast_2_3_2, void *c) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast_2_3_2, c);
+  int res = REAL(pthread_cond_broadcast_2_3_2)(c);
   return res;
 }
 
-TSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
+TSAN_INTERCEPTOR(int, pthread_cond_wait_2_3_2, void *c, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait_2_3_2, c, m);
   MutexUnlock(thr, pc, (uptr)m);
-  int res = REAL(pthread_cond_wait)(c, m);
+  int res = REAL(pthread_cond_wait_2_3_2)(c, m);
   MutexLock(thr, pc, (uptr)m);
   return res;
 }
 
-TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
+TSAN_INTERCEPTOR(int, pthread_cond_timedwait_2_3_2, void *c, void *m,
+    void *abstime) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_2_3_2, c, m, abstime);
   MutexUnlock(thr, pc, (uptr)m);
-  int res = REAL(pthread_cond_timedwait)(c, m, abstime);
+  int res = REAL(pthread_cond_timedwait_2_3_2)(c, m, abstime);
   MutexLock(thr, pc, (uptr)m);
   return res;
 }
@@ -1984,12 +1981,18 @@ void InitializeInterceptors() {
   TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
   TSAN_INTERCEPT(pthread_rwlock_unlock);
 
-  // TSAN_INTERCEPT(pthread_cond_init);
-  TSAN_INTERCEPT(pthread_cond_destroy);
-  TSAN_INTERCEPT(pthread_cond_signal);
-  TSAN_INTERCEPT(pthread_cond_broadcast);
-  TSAN_INTERCEPT(pthread_cond_wait);
-  TSAN_INTERCEPT(pthread_cond_timedwait);
+  INTERCEPT_FUNCTION_VER(pthread_cond_init, pthread_cond_init_2_3_2,
+      GLIBC_2.3.2);
+  INTERCEPT_FUNCTION_VER(pthread_cond_destroy, pthread_cond_destroy_2_3_2,
+      GLIBC_2.3.2);
+  INTERCEPT_FUNCTION_VER(pthread_cond_signal, pthread_cond_signal_2_3_2,
+      GLIBC_2.3.2);
+  INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, pthread_cond_broadcast_2_3_2,
+      GLIBC_2.3.2);
+  INTERCEPT_FUNCTION_VER(pthread_cond_wait, pthread_cond_wait_2_3_2,
+      GLIBC_2.3.2);
+  INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, pthread_cond_timedwait_2_3_2,
+      GLIBC_2.3.2);
 
   TSAN_INTERCEPT(pthread_barrier_init);
   TSAN_INTERCEPT(pthread_barrier_destroy);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Mon Sep  2 13:06:28 2013
@@ -169,12 +169,15 @@ void StatOutput(u64 *stat) {
   name[StatInt_pthread_rwlock_timedwrlock]
                                          = "  pthread_rwlock_timedwrlock      ";
   name[StatInt_pthread_rwlock_unlock]    = "  pthread_rwlock_unlock           ";
-  name[StatInt_pthread_cond_init]        = "  pthread_cond_init               ";
-  name[StatInt_pthread_cond_destroy]     = "  pthread_cond_destroy            ";
-  name[StatInt_pthread_cond_signal]      = "  pthread_cond_signal             ";
-  name[StatInt_pthread_cond_broadcast]   = "  pthread_cond_broadcast          ";
-  name[StatInt_pthread_cond_wait]        = "  pthread_cond_wait               ";
-  name[StatInt_pthread_cond_timedwait]   = "  pthread_cond_timedwait          ";
+  name[StatInt_pthread_cond_init_2_3_2]  = "  pthread_cond_init               ";
+  name[StatInt_pthread_cond_destroy_2_3_2]
+                                         = "  pthread_cond_destroy            ";
+  name[StatInt_pthread_cond_signal_2_3_2]= "  pthread_cond_signal             ";
+  name[StatInt_pthread_cond_broadcast_2_3_2]
+                                         = "  pthread_cond_broadcast          ";
+  name[StatInt_pthread_cond_wait_2_3_2]  = "  pthread_cond_wait               ";
+  name[StatInt_pthread_cond_timedwait_2_3_2]
+                                         = "  pthread_cond_timedwait          ";
   name[StatInt_pthread_barrier_init]     = "  pthread_barrier_init            ";
   name[StatInt_pthread_barrier_destroy]  = "  pthread_barrier_destroy         ";
   name[StatInt_pthread_barrier_wait]     = "  pthread_barrier_wait            ";

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=189767&r1=189766&r2=189767&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Mon Sep  2 13:06:28 2013
@@ -164,12 +164,12 @@ enum StatType {
   StatInt_pthread_rwlock_trywrlock,
   StatInt_pthread_rwlock_timedwrlock,
   StatInt_pthread_rwlock_unlock,
-  StatInt_pthread_cond_init,
-  StatInt_pthread_cond_destroy,
-  StatInt_pthread_cond_signal,
-  StatInt_pthread_cond_broadcast,
-  StatInt_pthread_cond_wait,
-  StatInt_pthread_cond_timedwait,
+  StatInt_pthread_cond_init_2_3_2,
+  StatInt_pthread_cond_destroy_2_3_2,
+  StatInt_pthread_cond_signal_2_3_2,
+  StatInt_pthread_cond_broadcast_2_3_2,
+  StatInt_pthread_cond_wait_2_3_2,
+  StatInt_pthread_cond_timedwait_2_3_2,
   StatInt_pthread_barrier_init,
   StatInt_pthread_barrier_destroy,
   StatInt_pthread_barrier_wait,





More information about the llvm-commits mailing list