[compiler-rt] r179032 - [libsymbolized] If we can't find an address in the list of shared libraries, try to reload it.

Alexander Potapenko glider at google.com
Mon Apr 8 10:46:34 PDT 2013


Author: glider
Date: Mon Apr  8 12:46:34 2013
New Revision: 179032

URL: http://llvm.org/viewvc/llvm-project?rev=179032&view=rev
Log:
[libsymbolized] If we can't find an address in the list of shared libraries, try to reload it.

Add a regression test for the case where such behavior helps TSan:
  1. race is reported in the main module
  2. new shared library is loaded
  3. race is reported in the shared library


Added:
    compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/
    compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/lit.local.cfg
    compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/load_shared_lib-so.cc
    compiler-rt/trunk/lib/tsan/lit_tests/load_shared_lib.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc?rev=179032&r1=179031&r2=179032&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc Mon Apr  8 12:46:34 2013
@@ -239,6 +239,7 @@ class InternalSymbolizer {
 
 class Symbolizer {
  public:
+  Symbolizer() : modules_fresh_(false) { };
   uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
     if (max_frames == 0)
       return 0;
@@ -376,7 +377,8 @@ class Symbolizer {
   }
 
   LoadedModule *FindModuleForAddress(uptr address) {
-    if (modules_ == 0) {
+    bool modules_were_reloaded = false;
+    if (modules_ == 0 || !modules_fresh_) {
       modules_ = (LoadedModule*)(symbolizer_allocator.Allocate(
           kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
       CHECK(modules_);
@@ -384,14 +386,25 @@ class Symbolizer {
       // FIXME: Return this check when GetListOfModules is implemented on Mac.
       // CHECK_GT(n_modules_, 0);
       CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
+      modules_fresh_ = true;
+      modules_were_reloaded = true;
     }
     for (uptr i = 0; i < n_modules_; i++) {
       if (modules_[i].containsAddress(address)) {
         return &modules_[i];
       }
     }
+    // Reload the modules and look up again, if we haven't tried it yet.
+    if (!modules_were_reloaded) {
+      // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
+      // It's too aggressive to reload the list of modules each time we fail
+      // to find a module for a given address.
+      modules_fresh_ = false;
+      return FindModuleForAddress(address);
+    }
     return 0;
   }
+
   void ReportExternalSymbolizerError(const char *msg) {
     // Don't use atomics here for now, as SymbolizeCode can't be called
     // from multiple threads anyway.
@@ -406,6 +419,8 @@ class Symbolizer {
   static const uptr kMaxNumberOfModuleContexts = 1 << 14;
   LoadedModule *modules_;  // Array of module descriptions is leaked.
   uptr n_modules_;
+  // If stale, need to reload the modules before looking up addresses.
+  bool modules_fresh_;
 
   ExternalSymbolizer *external_symbolizer_;  // Leaked.
   InternalSymbolizer *internal_symbolizer_;  // Leaked.

Added: compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/lit.local.cfg?rev=179032&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/lit.local.cfg (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/lit.local.cfg Mon Apr  8 12:46:34 2013
@@ -0,0 +1,4 @@
+# Sources in this directory are compiled as shared libraries and used by
+# tests in parent directory.
+
+config.suffixes = []

Added: compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/load_shared_lib-so.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/load_shared_lib-so.cc?rev=179032&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/load_shared_lib-so.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/SharedLibs/load_shared_lib-so.cc Mon Apr  8 12:46:34 2013
@@ -0,0 +1,22 @@
+//===----------- load_shared_lib-so.cc --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stddef.h>
+
+int GLOB_SHARED = 0;
+
+extern "C"
+void *write_from_so(void *unused) {
+  GLOB_SHARED++;
+  return NULL;
+}

Added: compiler-rt/trunk/lib/tsan/lit_tests/load_shared_lib.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/load_shared_lib.cc?rev=179032&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/load_shared_lib.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/load_shared_lib.cc Mon Apr  8 12:46:34 2013
@@ -0,0 +1,44 @@
+// Check that if the list of shared libraries changes between the two race
+// reports, the second report occurring in a new shared library is still
+// symbolized correctly.
+
+// RUN: %clangxx_tsan -O1 %p/SharedLibs/load_shared_lib-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <string>
+
+int GLOB = 0;
+
+void *write_glob(void *unused) {
+  GLOB++;
+  return NULL;
+}
+
+void race_two_threads(void *(*access_callback)(void *)) {
+  pthread_t t1, t2;
+  pthread_create(&t1, NULL, access_callback, NULL);
+  pthread_create(&t2, NULL, access_callback, NULL);
+  pthread_join(t1, NULL);
+  pthread_join(t2, NULL);
+}
+
+int main(int argc, char *argv[]) {
+  std::string path = std::string(argv[0]) + std::string("-so.so");
+  race_two_threads(write_glob);
+  // CHECK: write_glob
+  void *lib = dlopen(path.c_str(), RTLD_NOW);
+    if (!lib) {
+    printf("error in dlopen(): %s\n", dlerror());
+    return 1;
+  }
+  void *(*write_from_so)(void *);
+  *(void **)&write_from_so = dlsym(lib, "write_from_so");
+  race_two_threads(write_from_so);
+  // CHECK: write_from_so
+  return 0;
+}





More information about the llvm-commits mailing list