[compiler-rt] r254600 - [tsan] Use re-exec method to enable interceptors on older versions of OS X

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 3 02:39:43 PST 2015


Author: kuba.brecka
Date: Thu Dec  3 04:39:43 2015
New Revision: 254600

URL: http://llvm.org/viewvc/llvm-project?rev=254600&view=rev
Log:
[tsan] Use re-exec method to enable interceptors on older versions of OS X

In AddressSanitizer, we have the MaybeReexec method to detect when we're running without DYLD_INSERT_LIBRARIES (in which case interceptors don't work) and re-execute with the environment variable set. On OS X 10.11+, this is no longer necessary, but to have ThreadSanitizer supported on older versions of OS X, let's use the same method as well. This patch moves the implementation from `asan/` into `sanitizer_common/`.

Differential Revision: http://reviews.llvm.org/D15123


Modified:
    compiler-rt/trunk/lib/asan/asan_internal.h
    compiler-rt/trunk/lib/asan/asan_linux.cc
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_win.cc
    compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc

Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Thu Dec  3 04:39:43 2015
@@ -75,8 +75,6 @@ void AsanCheckIncompatibleRT();
 
 void AsanOnDeadlySignal(int, void *siginfo, void *context);
 
-void DisableReexec();
-void MaybeReexec();
 void ReadContextStack(void *context, uptr *stack, uptr *ssize);
 void StopInitOrderChecking();
 

Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Thu Dec  3 04:39:43 2015
@@ -70,14 +70,6 @@ namespace __asan {
 
 void InitializePlatformInterceptors() {}
 
-void DisableReexec() {
-  // No need to re-exec on Linux.
-}
-
-void MaybeReexec() {
-  // No need to re-exec on Linux.
-}
-
 void *AsanDoesNotSupportStaticLinkage() {
   // This will fail to link with -static.
   return &_DYNAMIC;  // defined in link.h

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Thu Dec  3 04:39:43 2015
@@ -24,15 +24,6 @@
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_mac.h"
 
-#if !SANITIZER_IOS
-#include <crt_externs.h>  // for _NSGetArgv and _NSGetEnviron
-#else
-extern "C" {
-  extern char ***_NSGetArgv(void);
-}
-#endif
-
-#include <dlfcn.h>  // for dladdr()
 #include <fcntl.h>
 #include <libkern/OSAtomic.h>
 #include <mach-o/dyld.h>
@@ -58,176 +49,6 @@ bool PlatformHasDifferentMemcpyAndMemmov
   return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
 }
 
-extern "C"
-void __asan_init();
-
-static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
-LowLevelAllocator allocator_for_env;
-
-// Change the value of the env var |name|, leaking the original value.
-// If |name_value| is NULL, the variable is deleted from the environment,
-// otherwise the corresponding "NAME=value" string is replaced with
-// |name_value|.
-void LeakyResetEnv(const char *name, const char *name_value) {
-  char **env = GetEnviron();
-  uptr name_len = internal_strlen(name);
-  while (*env != 0) {
-    uptr len = internal_strlen(*env);
-    if (len > name_len) {
-      const char *p = *env;
-      if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
-        // Match.
-        if (name_value) {
-          // Replace the old value with the new one.
-          *env = const_cast<char*>(name_value);
-        } else {
-          // Shift the subsequent pointers back.
-          char **del = env;
-          do {
-            del[0] = del[1];
-          } while (*del++);
-        }
-      }
-    }
-    env++;
-  }
-}
-
-static bool reexec_disabled = false;
-
-void DisableReexec() {
-  reexec_disabled = true;
-}
-
-extern "C" double dyldVersionNumber;
-static const double kMinDyldVersionWithAutoInterposition = 360.0;
-
-bool DyldNeedsEnvVariable() {
-  // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
-  // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via
-  // GetMacosVersion() doesn't work for the simulator. Let's instead check
-  // `dyldVersionNumber`, which is exported by dyld, against a known version
-  // number from the first OS release where this appeared.
-  return dyldVersionNumber < kMinDyldVersionWithAutoInterposition;
-}
-
-void MaybeReexec() {
-  if (reexec_disabled) return;
-
-  // Make sure the dynamic ASan runtime library is preloaded so that the
-  // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
-  // ourselves.
-  Dl_info info;
-  CHECK(dladdr((void*)((uptr)__asan_init), &info));
-  char *dyld_insert_libraries =
-      const_cast<char*>(GetEnv(kDyldInsertLibraries));
-  uptr old_env_len = dyld_insert_libraries ?
-      internal_strlen(dyld_insert_libraries) : 0;
-  uptr fname_len = internal_strlen(info.dli_fname);
-  const char *dylib_name = StripModuleName(info.dli_fname);
-  uptr dylib_name_len = internal_strlen(dylib_name);
-
-  bool lib_is_in_env =
-      dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name);
-  if (DyldNeedsEnvVariable() && !lib_is_in_env) {
-    // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
-    // library.
-    char program_name[1024];
-    uint32_t buf_size = sizeof(program_name);
-    _NSGetExecutablePath(program_name, &buf_size);
-    char *new_env = const_cast<char*>(info.dli_fname);
-    if (dyld_insert_libraries) {
-      // Append the runtime dylib name to the existing value of
-      // DYLD_INSERT_LIBRARIES.
-      new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
-      internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
-      new_env[old_env_len] = ':';
-      // Copy fname_len and add a trailing zero.
-      internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
-                       fname_len + 1);
-      // Ok to use setenv() since the wrappers don't depend on the value of
-      // asan_inited.
-      setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
-    } else {
-      // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
-      setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
-    }
-    VReport(1, "exec()-ing the program with\n");
-    VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
-    VReport(1, "to enable ASan wrappers.\n");
-    execv(program_name, *_NSGetArgv());
-
-    // We get here only if execv() failed.
-    Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
-           "which is required for ASan to work. ASan tried to set the "
-           "environment variable and re-execute itself, but execv() failed, "
-           "possibly because of sandbox restrictions. Make sure to launch the "
-           "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
-    CHECK("execv failed" && 0);
-  }
-
-  if (!lib_is_in_env)
-    return;
-
-  // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
-  // the dylib from the environment variable, because interceptors are installed
-  // and we don't want our children to inherit the variable.
-
-  uptr env_name_len = internal_strlen(kDyldInsertLibraries);
-  // Allocate memory to hold the previous env var name, its value, the '='
-  // sign and the '\0' char.
-  char *new_env = (char*)allocator_for_env.Allocate(
-      old_env_len + 2 + env_name_len);
-  CHECK(new_env);
-  internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
-  internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
-  new_env[env_name_len] = '=';
-  char *new_env_pos = new_env + env_name_len + 1;
-
-  // Iterate over colon-separated pieces of |dyld_insert_libraries|.
-  char *piece_start = dyld_insert_libraries;
-  char *piece_end = NULL;
-  char *old_env_end = dyld_insert_libraries + old_env_len;
-  do {
-    if (piece_start[0] == ':') piece_start++;
-    piece_end = REAL(strchr)(piece_start, ':');
-    if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
-    if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
-    uptr piece_len = piece_end - piece_start;
-
-    char *filename_start =
-        (char *)internal_memrchr(piece_start, '/', piece_len);
-    uptr filename_len = piece_len;
-    if (filename_start) {
-      filename_start += 1;
-      filename_len = piece_len - (filename_start - piece_start);
-    } else {
-      filename_start = piece_start;
-    }
-
-    // If the current piece isn't the runtime library name,
-    // append it to new_env.
-    if ((dylib_name_len != filename_len) ||
-        (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
-      if (new_env_pos != new_env + env_name_len + 1) {
-        new_env_pos[0] = ':';
-        new_env_pos++;
-      }
-      internal_strncpy(new_env_pos, piece_start, piece_len);
-      new_env_pos += piece_len;
-    }
-    // Move on to the next piece.
-    piece_start = piece_end;
-  } while (piece_start < old_env_end);
-
-  // Can't use setenv() here, because it requires the allocator to be
-  // initialized.
-  // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
-  // a separate function called after InitializeAllocator().
-  if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
-  LeakyResetEnv(kDyldInsertLibraries, new_env);
-}
-
 // No-op. Mac does not support static linkage anyway.
 void *AsanDoesNotSupportStaticLinkage() {
   return 0;

Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Thu Dec  3 04:39:43 2015
@@ -175,14 +175,6 @@ void PlatformTSDDtor(void *tsd) {
 // }}}
 
 // ---------------------- Various stuff ---------------- {{{
-void DisableReexec() {
-  // No need to re-exec on Windows.
-}
-
-void MaybeReexec() {
-  // No need to re-exec on Windows.
-}
-
 void *AsanDoesNotSupportStaticLinkage() {
 #if defined(_DEBUG)
 #error Please build the runtime with a non-debug CRT: /MD or /MT

Modified: compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc Thu Dec  3 04:39:43 2015
@@ -34,7 +34,7 @@
 // Make sure __asan_init is called before any test case is run.
 struct AsanInitCaller {
   AsanInitCaller() {
-    __asan::DisableReexec();
+    DisableReexec();
     __asan_init();
   }
 };

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Thu Dec  3 04:39:43 2015
@@ -733,6 +733,9 @@ struct SignalContext {
 
 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
 
+void DisableReexec();
+void MaybeReexec();
+
 }  // namespace __sanitizer
 
 inline void *operator new(__sanitizer::operator_new_size_type size,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Thu Dec  3 04:39:43 2015
@@ -1143,6 +1143,14 @@ void GetPcSpBp(void *context, uptr *pc,
 #endif
 }
 
+void DisableReexec() {
+  // No need to re-exec on Linux.
+}
+
+void MaybeReexec() {
+  // No need to re-exec on Linux.
+}
+
 } // namespace __sanitizer
 
 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Thu Dec  3 04:39:43 2015
@@ -43,7 +43,16 @@ extern char **environ;
 #define SANITIZER_OS_TRACE 0
 #endif
 
+#if !SANITIZER_IOS
+#include <crt_externs.h>  // for _NSGetArgv and _NSGetEnviron
+#else
+extern "C" {
+  extern char ***_NSGetArgv(void);
+}
+#endif
+
 #include <asl.h>
+#include <dlfcn.h>  // for dladdr()
 #include <errno.h>
 #include <fcntl.h>
 #include <libkern/OSAtomic.h>
@@ -486,6 +495,173 @@ void GetPcSpBp(void *context, uptr *pc,
 # endif
 }
 
+static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
+LowLevelAllocator allocator_for_env;
+
+// Change the value of the env var |name|, leaking the original value.
+// If |name_value| is NULL, the variable is deleted from the environment,
+// otherwise the corresponding "NAME=value" string is replaced with
+// |name_value|.
+void LeakyResetEnv(const char *name, const char *name_value) {
+  char **env = GetEnviron();
+  uptr name_len = internal_strlen(name);
+  while (*env != 0) {
+    uptr len = internal_strlen(*env);
+    if (len > name_len) {
+      const char *p = *env;
+      if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
+        // Match.
+        if (name_value) {
+          // Replace the old value with the new one.
+          *env = const_cast<char*>(name_value);
+        } else {
+          // Shift the subsequent pointers back.
+          char **del = env;
+          do {
+            del[0] = del[1];
+          } while (*del++);
+        }
+      }
+    }
+    env++;
+  }
+}
+
+static bool reexec_disabled = false;
+
+void DisableReexec() {
+  reexec_disabled = true;
+}
+
+extern "C" double dyldVersionNumber;
+static const double kMinDyldVersionWithAutoInterposition = 360.0;
+
+bool DyldNeedsEnvVariable() {
+  // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
+  // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via
+  // GetMacosVersion() doesn't work for the simulator. Let's instead check
+  // `dyldVersionNumber`, which is exported by dyld, against a known version
+  // number from the first OS release where this appeared.
+  return dyldVersionNumber < kMinDyldVersionWithAutoInterposition;
+}
+
+void MaybeReexec() {
+  if (reexec_disabled) return;
+
+  // Make sure the dynamic runtime library is preloaded so that the
+  // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
+  // ourselves.
+  Dl_info info;
+  CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
+  char *dyld_insert_libraries =
+      const_cast<char*>(GetEnv(kDyldInsertLibraries));
+  uptr old_env_len = dyld_insert_libraries ?
+      internal_strlen(dyld_insert_libraries) : 0;
+  uptr fname_len = internal_strlen(info.dli_fname);
+  const char *dylib_name = StripModuleName(info.dli_fname);
+  uptr dylib_name_len = internal_strlen(dylib_name);
+
+  bool lib_is_in_env = dyld_insert_libraries &&
+                       internal_strstr(dyld_insert_libraries, dylib_name);
+  if (DyldNeedsEnvVariable() && !lib_is_in_env) {
+    // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
+    // library.
+    char program_name[1024];
+    uint32_t buf_size = sizeof(program_name);
+    _NSGetExecutablePath(program_name, &buf_size);
+    char *new_env = const_cast<char*>(info.dli_fname);
+    if (dyld_insert_libraries) {
+      // Append the runtime dylib name to the existing value of
+      // DYLD_INSERT_LIBRARIES.
+      new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
+      internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
+      new_env[old_env_len] = ':';
+      // Copy fname_len and add a trailing zero.
+      internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
+                       fname_len + 1);
+      // Ok to use setenv() since the wrappers don't depend on the value of
+      // asan_inited.
+      setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
+    } else {
+      // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
+      setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
+    }
+    VReport(1, "exec()-ing the program with\n");
+    VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
+    VReport(1, "to enable wrappers.\n");
+    execv(program_name, *_NSGetArgv());
+
+    // We get here only if execv() failed.
+    Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
+           "which is required for the sanitizer to work. We tried to set the "
+           "environment variable and re-execute itself, but execv() failed, "
+           "possibly because of sandbox restrictions. Make sure to launch the "
+           "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
+    CHECK("execv failed" && 0);
+  }
+
+  if (!lib_is_in_env)
+    return;
+
+  // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
+  // the dylib from the environment variable, because interceptors are installed
+  // and we don't want our children to inherit the variable.
+
+  uptr env_name_len = internal_strlen(kDyldInsertLibraries);
+  // Allocate memory to hold the previous env var name, its value, the '='
+  // sign and the '\0' char.
+  char *new_env = (char*)allocator_for_env.Allocate(
+      old_env_len + 2 + env_name_len);
+  CHECK(new_env);
+  internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
+  internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
+  new_env[env_name_len] = '=';
+  char *new_env_pos = new_env + env_name_len + 1;
+
+  // Iterate over colon-separated pieces of |dyld_insert_libraries|.
+  char *piece_start = dyld_insert_libraries;
+  char *piece_end = NULL;
+  char *old_env_end = dyld_insert_libraries + old_env_len;
+  do {
+    if (piece_start[0] == ':') piece_start++;
+    piece_end = internal_strchr(piece_start, ':');
+    if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
+    if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
+    uptr piece_len = piece_end - piece_start;
+
+    char *filename_start =
+        (char *)internal_memrchr(piece_start, '/', piece_len);
+    uptr filename_len = piece_len;
+    if (filename_start) {
+      filename_start += 1;
+      filename_len = piece_len - (filename_start - piece_start);
+    } else {
+      filename_start = piece_start;
+    }
+
+    // If the current piece isn't the runtime library name,
+    // append it to new_env.
+    if ((dylib_name_len != filename_len) ||
+        (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
+      if (new_env_pos != new_env + env_name_len + 1) {
+        new_env_pos[0] = ':';
+        new_env_pos++;
+      }
+      internal_strncpy(new_env_pos, piece_start, piece_len);
+      new_env_pos += piece_len;
+    }
+    // Move on to the next piece.
+    piece_start = piece_end;
+  } while (piece_start < old_env_end);
+
+  // Can't use setenv() here, because it requires the allocator to be
+  // initialized.
+  // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
+  // a separate function called after InitializeAllocator().
+  if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
+  LeakyResetEnv(kDyldInsertLibraries, new_env);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Thu Dec  3 04:39:43 2015
@@ -762,6 +762,14 @@ void CheckVMASize() {
   // Do nothing.
 }
 
+void DisableReexec() {
+  // No need to re-exec on Windows.
+}
+
+void MaybeReexec() {
+  // No need to re-exec on Windows.
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=254600&r1=254599&r2=254600&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Thu Dec  3 04:39:43 2015
@@ -323,6 +323,9 @@ void Initialize(ThreadState *thr) {
   InitializeFlags(&ctx->flags, options);
   InitializePlatformEarly();
 #ifndef SANITIZER_GO
+  // Re-exec ourselves if we need to set additional env or command line args.
+  MaybeReexec();
+
   InitializeAllocator();
   ReplaceSystemMalloc();
 #endif




More information about the llvm-commits mailing list